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?

Answers


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)) {
                                filtered_parts.push(part);
                            }
                        }

                        // Update rule selectors or delete
                        //
                        if (filtered_parts.length > 0) {
                            css_rule.selectorText = filtered_parts.join(',');
                        } else {
                            stylesheet.deleteRule(css_rules_index);
                        }
                    }
                }
            }
        }
    } 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 https://gist.github.com/4404503 
// via https://twitter.com/javan/status/284873379062890496
// + https://twitter.com/pennig/status/285790598642946048
// re http://retrogamecrunch.com/tmp/hover
if ('createTouch' in document)
{
    try
    {
        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))
                {
                    sheet.deleteRule(j);
                }
            }
        }
    }
    catch(e){}
}

Need Your Help

How to prevent malicious *.js scripts from executing in Node.js

node.js security module

I'm using Node.js to create the web service. In the implementation, I consumed many third party modules which are installed via npm. There is security issue if there is malicious *.js scripts in the

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.