Fix :hover issues on iOS devices, universally with jQuery

At the moment I'm having a following issue, when I first tap on something the :hover state gets triggered and I than need to tap second time in order to actually click an element. Fixes I found were targeting just some elements, and have been provided year or more ago. I thought maybe something recent has occurred, which allows to fix this issue universally? maybe get rid of all :hover rules in once, if user is on a touch device?


Are you sure that :hover is what's happening? Often the css rule will be on

:hover, :focus

or something like that. :hover shouldn't happen at all on a touch device, but :focus would occur once the link is touched. You could just break your hover and focus rules apart from each other. Alternatively, you could use modernizr to detect touch support and style against the classes it creates on the body element.

Thanks Jarrod!

Your code works great, except for cases of compound CSS selectors.

I extended your code to work with compound selectors:

var disableCSSHoverSelectors = function (param_window) {
    'use strict';

    var css_style_rule_type, hover_expression, stylesheet_index, stylesheet, css_rules_index, css_rules, css_rule, parts, filtered_parts, parts_index, part;

    try {
        // Touch enabled?
        if (('ontouchstart' in param_window) || ((param_window.DocumentTouch) && (param_window.document instanceof DocumentTouch))) {
            // Determine style rule type
            css_style_rule_type = param_window.CSSRule.STYLE_RULE;

            // Define hover expression
            hover_expression = /:hover/;

            // Iterate stylesheets
            for (stylesheet_index = 0; stylesheet_index < param_window.document.styleSheets.length; stylesheet_index += 1) {
                stylesheet = param_window.document.styleSheets[stylesheet_index];

                // Iterate rules
                css_rules = stylesheet.cssRules;
                if (css_rules === undefined) {
                    css_rules = stylesheet.rules;
                for (css_rules_index = css_rules.length - 1; css_rules_index >= 0; css_rules_index -= 1) {
                    css_rule = css_rules[css_rules_index];

                    // Check rule type
                    if (css_rule.type === css_style_rule_type) {
                        // Expand compound selectors
                        if (css_rule.selectorText.indexOf(',') !== -1) {
                            parts = css_rule.selectorText.split(',');
                        } else {
                            parts = [ css_rule.selectorText ];

                        // Filter individual selectors
                        filtered_parts = [];
                        for (parts_index = 0; parts_index < parts.length; parts_index += 1) {
                            part = parts[parts_index];

                            if (!hover_expression.test(part)) {

                        // Update rule selectors or delete
                        if (filtered_parts.length > 0) {
                            css_rule.selectorText = filtered_parts.join(',');
                        } else {
    } catch (ignore) {
        // Not fatal

Here is something a bit closer to what your asking for. It will remove hover styles from your parsed CSS.

iOS :hover fix

// disable :hover on touch devices
// based on 
// via
// +
// re
if ('createTouch' in document)
        var ignore = /:hover/;
        for (var i=0; i<document.styleSheets.length; i++)
            var sheet = document.styleSheets[i];
            for (var j=sheet.cssRules.length-1; j>=0; j--)
                var rule = sheet.cssRules[j];
                if (rule.type === CSSRule.STYLE_RULE && ignore.test(rule.selectorText))

Need Your Help

How to 'append' the background with more styles in CSS?

html css

I need a way to 'append' the style to the same div in css. I know this can be done with jQuery, but I wonder if it'll be possible just using the stylesheet.

req is not readable after middleware used

node.js express passport.js

I'm attempting to secure an API endpoint of mine with passport running on node.js version 0.8.2. The controller function I have looks something like this:

How to add a form name to a form in ruby?

ruby-on-rails ruby

How can I add a form name to the following line?

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.