How to remove / ignore: style css on touch devices

I want to ignore all ads :hover CSS if the user visits our website using a touch device. Since CSS :hover does not make sense, and it may even bother if the tablet launches it when pressed / pressed, because then it can stick until the element loses focus. Honestly, I don’t know why touch devices feel the need to run :hover first - but this is a reality, so this problem is also a reality.

 a:hover { color:blue; border-color:green; // etc. > ignore all at once for touch devices } 

So, (how) can I remove / ignore all CSS :hover declarations immediately (without having to know each) for touch devices after they are declared?

+93
html css touch hover
May 27 '14 at 9:06
source share
13 answers

There are several solutions to this problem.

Quick'n'dirty - delete: hover styles using JS

You can remove all CSS rules containing :hover using Javascript. This has the advantage that you don’t have to touch CSS and be compatible even with older browsers.

 function hasTouch() { return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; } if (hasTouch()) { // remove all :hover stylesheets try { // prevent exception on browsers not supporting DOM styleSheets properly for (var si in document.styleSheets) { var styleSheet = document.styleSheets[si]; if (!styleSheet.rules) continue; for (var ri = styleSheet.rules.length - 1; ri >= 0; ri--) { if (!styleSheet.rules[ri].selectorText) continue; if (styleSheet.rules[ri].selectorText.match(':hover')) { styleSheet.deleteRule(ri); } } } } catch (ex) {} } 

Limitations: style sheets must be in the same domain (this means that there is no CDN). Disables freezes on mixed mouse and touch devices such as Surface, which will damage the UX.

CSS-only - using media queries

Put all your rules: hover in the @media block:

 @media (hover: hover) { a:hover { color: blue; } } 

or, conversely, override all hover rules (compatible with older browsers):

 a:hover { color: blue; } @media (hover: none) { a:hover { color: inherit; } } 

Limitations: works only with iOS 9.0+, Chrome for Android or Android 5.0+ when using WebView. hover: hover breaks the effects of hovering on older browsers, hover: none requires overriding all previously defined CSS rules. Both are incompatible with mixed mouse and touch devices .

The most reliable is to use a special CSS class and detect touch through JS

This method requires the addition of all hover rules using body.hasHover . (or the class name of your choice)

 body.hasHover a:hover { color: blue; } 

The hasHover class can be added using hasTouch() from the first example:

 if (!hasTouch()) { document.body.className += ' hasHover'; } 

However, this problem has the same problems with mixed touch devices as the previous examples, which leads us to a final solution. Turn on hover effects each time you move the mouse cursor; turn off hover effects when a touch is detected.

 function watchForHover() { var hasHoverClass = false; var container = document.body; var lastTouchTime = 0; function enableHover() { // filter emulated events coming from touch events if (new Date() - lastTouchTime < 500) return; if (hasHoverClass) return; container.className += ' hasHover'; hasHoverClass = true; } function disableHover() { if (!hasHoverClass) return; container.className = container.className.replace(' hasHover', ''); hasHoverClass = false; } function updateLastTouchTime() { lastTouchTime = new Date(); } document.addEventListener('touchstart', updateLastTouchTime, true); document.addEventListener('touchstart', disableHover, true); document.addEventListener('mousemove', enableHover, true); enableHover(); } watchForHover(); 

This should work mostly in any browser and enable / disable hover styles as needed. Try it here: https://jsfiddle.net/dkz17jc5/19/

+112
May 18 '15 at 12:59
source share
— -

Adaptation of a pointer to help!

Since this has not been affected after a while, you can use:

 a:link { color: red; } a:hover { color:blue; } @media (hover: none) { a:link { color: red; } } 

Watch the demo in your browser and phone browser . It is supported by modern touch devices .

Note. Keep in mind that since the primary input (feature) of the Surface PC is a mouse, it will become a blue link, even if it is a separate screen (tablet). Browsers will (should) always set the most accurate input options by default.

+32
Mar 22 '17 at 3:04 on
source share

I am currently dealing with a similar problem.

There are two main options at once: (1) checking the user line or (2) saving individual mobile pages using a different URL and users choosing what is best for them.

  • If you can use a language with a channel on a channel, such as PHP or Ruby, you can check the user string of the device requesting the page and just serve the same content, but with a <link rel="mobile.css" /> instead regular style.

User strings have identification information about the browser, renderer, operating system, etc. It’s up to you to decide which devices “touch” and “do not touch”. Perhaps you can find this information somewhere and transfer it to your system.

A. If you are allowed to ignore old browsers , you just need to add one rule to normal, not mobile css, namely: EDIT: Erk. After some experimentation, I found that the rule below also disables the ability to track links in webkit browsers in addition to simply disabling aesthetic effects - see http://jsfiddle.net/3nkcdeao/
Thus, you should be a little more selective about how you change the rules for mobile business than what I show here, but this can be a useful starting point:

 * { pointer-events: none !important; /* only use !important if you have to */ } 

As a side element, disabling the parent event pointers and then explicitly including them in the child currently causes all the hanging effects on the parent to be activated again if the child is in :hover .
See http://jsfiddle.net/38Lookhp/5/

C. If you support legacy web renderers, you will have to work a bit to remove any rules that set special styles during :hover . To save time, you can simply create an automatic copy of + sed ing, which you run in your standard style sheets to create mobile versions. This will allow you to simply write / update the standard code and hide all the style rules that use :hover for the mobile version of your pages.

  1. (I) Also, just tell your users that you have m.website.com for mobile in addition to your website. Although the subdomain is the most common way, you can also have some other predictable modification to this URL to allow mobile users to access the modified pages. At this point, you will want to make sure that they don’t need to change the URL every time they go to another part of the site.

Again, here you can simply add an extra rule or two to your stylesheets or do something more complex using sed or a similar utility. It would probably be the easiest to apply: not to your style rules, like div:not(.disruptive):hover {... , in which you would add class="disruptive" to elements that annoy things for mobile users, using js or server language, instead of iterating over CSS.

  1. (II) You can combine the first two and (if you suspect that the user has wandered on the wrong version of the page), you can assume that they switch to / from the mobile type display or just have a link somewhere that allows users to pounce ahead and back. As already mentioned, @media queries can also be helpful in determining what is used for the visit.

  2. (III) If you decide to use the jQuery solution when you know which devices “touch” and which don't, you can find CSS hover not being ignored on touch devices .

+7
Nov 15 '14 at 1:59
source share

try the following:

 @media (hover:<s>on-demand</s>) { button:hover { background-color: #color-when-NOT-touch-device; } } 

UPDATE: unfortunately, W3C removed this property from the specifications ( https://github.com/w3c/csswg-drafts/commit/2078b46218f7462735bb0b5107c9a3e84fb4c4b1 ).

+6
Apr 08 '16 at 22:59
source share

I ran into the same problem (in my case with Samsung mobile browsers) and therefore came across this question.

Thanks to Calsal's answer, I found something that seems to exclude almost all desktop browsers, because it seems to be recognized by the mobile browsers I tried (see screenshot from the compiled table: CSS pointer function detection table ).

MDN web documents claim

The CSS @media function of the pointer can be used to apply styles depending on whether the main user input mechanism is a pointing device, and if so, how accurate

,

I found that the pointer: coarse is something that is not known to all desktop browsers in the attached table, but is known to all mobile browsers in the same table. This seems like the most effective choice, because all other pointer keyword values ​​give conflicting results.

Therefore, you could create a media query as described by Calsal, but slightly modified. It uses reverse logic to exclude all touch devices.

Sass mixin:

 @mixin hover-supported { /* * https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer * coarse: The primary input mechanism includes a pointing device of limited accuracy. */ @media not all and (pointer: coarse) { &:hover { @content; } } } a { color:green; border-color:blue; @include hover-supported() { color:blue; border-color:green; } } 

Compiled CSS:

 a { color: green; border-color: blue; } @media not all and (pointer: coarse) { a:hover { color: blue; border-color: green; } } 

This is also described in this entity, which I created after investigating the problem. Codepen for empirical research.

UPDATE : At the time of writing this update, 2018-08-23 and indicated by @DmitriPavlutin, this technique does not seem to work with Firefox desktop anymore.

+6
Apr 21 '18 at 17:33
source share

You can use Modernizr JS (see also this https://stackoverflow.com/a/3/9149/ ) and create a custom JS function:

 function is_touch_device() { return 'ontouchstart' in window // works on most browsers || navigator.maxTouchPoints; // works on IE10/11 and Surface }; if ( is_touch_device() ) { $('html').addClass('touch'); } else { $('html').addClass('no-touch'); } 

before defining support for touch events in the browser, and then assign a regular CSS property by going through an element with the html.no-touch class, for example:

 html.touch a { width: 480px; } /* FOR THE DESKTOP, SET THE HOVER STATE */ html.no-touch a:hover { width: auto; color:blue; border-color:green; } 
+4
Jul 26 '16 at 15:25
source share

This is also a possible workaround, but you have to go through your css and add the .no-touch class in front of the hover styles.

JavaScript:

 if (!("ontouchstart" in document.documentElement)) { document.documentElement.className += " no-touch"; } 

CSS example:

 <style> p span { display: none; } .no-touch p:hover span { display: inline; } </style> <p><a href="/">Tap me</a><span>You tapped!</span></p> 

Source

Ps But we must remember that more and more touch devices are coming onto the market that simultaneously support mouse support.

+1
Nov 05 '15 at 17:55
source share

It may not be the perfect solution (and it with jQuery), but it may be the direction / concept that needs to be worked on: how about doing it the other way around? This means disabling the states: hover css by default and activating them if the mousemove event is detected anywhere in the document. Of course, this does not work if someone has disabled js. What else can do this against it?

Maybe so:

CSS

 /* will only work if html has class "mousedetected" */ html.mousedetected a:hover { color:blue; border-color:green; } 

JQuery

 /* adds "mousedetected" class to html element if mouse moves (which should never happen on touch-only devices shouldn't it?) */ $("body").mousemove( function() { $("html").addClass("mousedetected"); }); 
+1
Dec 12 '16 at 10:29
source share

According to Jason's answer, we can only address devices that do not support hover with pure CSS media requests. We can also only access devices that support hover, for example, moogal's answer to a similar question, with @media not all and (hover: none) . It looks weird, but it works.

From this I made a Sass mixin for easier use:

 @mixin hover-supported { @media not all and (hover: none) { &:hover { @content; } } } 

Update 2019-05-15 : I recommend this article from Medium, which covers all the different devices that we can target using CSS. In fact, this is a mixture of these multimedia rules, combining them for specific purposes:

 @media (hover: hover) { /* Device that can hover (desktops) */ } @media (hover: none) { /* Device that can not hover with ease */ } @media (pointer: coarse) { /* Device with limited pointing accuracy (touch) */ } @media (pointer: fine) { /* Device with accurate pointing (desktop, stylus-based) */ } @media (pointer: none) { /* Device with no pointing */ } 

An example for specific purposes:

 @media (hover: none) and (pointer: coarse) { /* Smartphones and touchscreens */ } @media (hover: hover) and (pointer: fine) { /* Desktops with mouse */ } 

I love mixins, here's how I use them:

 @mixin is-touch { @media (hover: none) and (pointer: coarse) { @content; } } 
+1
Aug 22 '17 at 14:23
source share

It was useful for me: link

 function hoverTouchUnstick() { // Check if the device supports touch events if('ontouchstart' in document.documentElement) { // Loop through each stylesheet for(var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) { var sheet = document.styleSheets[sheetI]; // Verify if cssRules exists in sheet if(sheet.cssRules) { // Loop through each rule in sheet for(var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) { var rule = sheet.cssRules[ruleI]; // Verify rule has selector text if(rule.selectorText) { // Replace hover psuedo-class with active psuedo-class rule.selectorText = rule.selectorText.replace(":hover", ":active"); } } } } } } 
0
Jul 06 '15 at 14:53
source share

Try this (I use background and background-color in this example):

 var ClickEventType = ((document.ontouchstart !== null) ? 'click' : 'touchstart'); if (ClickEventType == 'touchstart') { $('a').each(function() { // save original.. var back_color = $(this).css('background-color'); var background = $(this).css('background'); $(this).attr('data-back_color', back_color); $(this).attr('data-background', background); }); $('a').on('touchend', function(e) { // overwrite with original style.. var background = $(this).attr('data-background'); var back_color = $(this).attr('data-back_color'); if (back_color != undefined) { $(this).css({'background-color': back_color}); } if (background != undefined) { $(this).css({'background': background}); } }).on('touchstart', function(e) { // clear added stlye="" elements.. $(this).css({'background': '', 'background-color': ''}); }); } 

CSS:

 a { -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } 
0
Jun 16 '19 at
source share

This can be solved with sass / scss and a media query with the desired breakpoint.

 .myclass { background-color: blue; &:hover { @media screen and (max-width: 320px) { background-color: red; } } } 
-one
Apr 18 '17 at 20:49 on
source share

Try this simple 2019 jquery solution, although it has been around for a long time;

  1. add this plugin to the head:

    src = "https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"

  2. add this to JS:

    $ ("*"). on ("touchend", function (e) {$ (this) .focus ();}); // applies to all elements

  3. Some suggested options for this:

    $ (": input ,: checkbox,"). on ("touchend", function (e) {(this) .focus);}); // specify elements

    $ ("*"). on ("click, touchend", function (e) {$ (this) .focus ();}); // enable click event

    css: body {cursor: pointer; } // tap somewhere to end focus

Notes

  • place the plugin in front of bootstrap.js to avoid affecting tooltips
  • tested only on iphone XR ios 12.1.12 and ipad 3 ios 9.3.5 using Safari or Chrome.

Recommendations:

https://code.jquery.com/ui/

https://api.jquery.com/category/selectors/jquery-selector-extensions/

-one
Jan 11 '19 at 6:05
source share



All Articles