19

If you tap on an element on iOS, the browser fires mouseover/mousemove events and renders :hover styles. If it detects „content change“ in this process no click event gets fired and you have to tap again to fire a click event. This is documented on developer.apple.com.

I had the issue on a webpage that a „content change“ was detected even though no mouse events or :hover styles were applied. It took a while, but I was able to reduce the webpage to a small test case:

<style>
    a:hover { color: red }
    foo + * { color: red }
</style>
<a href="about:blank">foo</a>
<input type="search">

On this page you have to tap two times on the "foo" link to navigate. Tested with iPad mini and iPhone (both native and in the simulator).

After that I found this blog post with a similar issue. But the only fix that works for my issue is the following CSS:

input[type=search]::-webkit-search-cancel-button {
    display: none;
}

But I can’t use this workaround if I want the search cancel button to be visible.

Is there an other workaround for this issue?

I posted this bug on bugreport.apple.com several days ago, without a reaction of apple until now. This bug seems to be in iOS 6 and 7 and it would be great if it gets fixed some day.

How do I find out if this is a webkit or an iOS bug?

Where is the right place to report this bug?


UPDATE

This bug seems to be fixed in iOS 8. Tested with iPad mini and iPhone (both native and in the simulator).

UPDATE 2

Bug wasn’t completely fixed in iOS 8, it still appears if you put some CSS between the braces, e.g. color: red. I updated the test case to show the bug also in iOS 8.

UPDATE 3

The bug is not fixed in iOS 9, still no reaction from bugreport.apple.com other than “behaves as intended”.

ausi
  • 7,253
  • 2
  • 31
  • 48
  • 1
    `foo + * { color: red }` - what is the purpose of this css? – Adnan May 15 '15 at 16:03
  • @adnan This rule is needed to let the bug appear. It doesn’t match any element so it shouldn’t effect the behavior of the link. I think it could be any selector with `+ *` in it. – ausi May 15 '15 at 16:10
  • 1
    Just tested on iPhone, yes very interesting bug! – Adnan May 15 '15 at 16:27
  • The double tap problem also happens if one applies an underline effect on hover to links without any input element in the page. Here is an example: http://sandbox.saeidmohadjer.com/ios-bug.html – smohadjer Sep 13 '15 at 20:32
  • @smohadjer I cannot confirm that, your example works fine at the first tap in iOS 8 and iOS 7 – ausi Sep 14 '15 at 06:51
  • @ausi Strange! For me it doesn't, neither on iPhone nor on iPad (both iOS 8.4.1), Make sure you refresh page or clean cache before tapping the links. – smohadjer Sep 14 '15 at 10:50
  • @smohadjer Tested it in different iOS versions, it always worked at the first tap. See https://vimeo.com/139194997 – ausi Sep 14 '15 at 11:50
  • Did you test on actual device or a simulator? – smohadjer Sep 14 '15 at 16:30
  • @smohadjer Tested on iPhone, iPad and simulator. Is there a reason for the `display: block;` in your example? – ausi Sep 14 '15 at 16:38
  • Yes, I encountered this problem on navigation of a site I was building. I used display: block and padding on anchors to increase clickable area of each link. What I find interesting is that if I remove any of css rules in my test page, links work on first click! – smohadjer Sep 15 '15 at 22:58
  • unable to reproduce now - this is an issue as I actually want this behaviour and I can't get the double tap with :hover in iOS9.2 – benbyford Mar 07 '16 at 17:33
  • @benbyford I still can reproduce it in iOS 9.2 – ausi Mar 07 '16 at 19:28
  • Looks like I found a solution. [Visit Here ...](http://stackoverflow.com/questions/33922957/disable-double-tap-to-click-on-touchscreen-ios-devices) – Alaa M. Jaddou Mar 06 '17 at 09:47

2 Answers2

4

I'd disable the hover effect for touch devices as a general rule of practice.

The trick is to allow for devices that can have touch but where the touch isn't used to still get the hover effects.

I'd disable all hover effect unless you're using hover effects to create dropdown menus as those actually need the double tab, but for the rest it's quite counterproductive.

What I'm using is a simple script that removes a class on the body whenever a touchstart event occurs.

So I start out with a body that's got a class no-touch

<body class="hoverok">

And then add the following as javascript, to remove that tag on the first touchstart:

(function () {
 function antitouch() {
  if (!('addEventListener' in window)) {
   return;
  }
  var bodyElement = document.querySelector('body');
  function touchStart () {
   document.querySelector('body').classList.remove('hoverok');
   bodyElement.removeEventListener('touchstart', touchStart);
  }
  bodyElement.addEventListener('touchstart', touchStart);
 }
 if (window.addEventListener) {
    window.addEventListener('DOMContentLoaded', antitouch, false);
  } else {
    window.attachEvent('onload', antitouch);
  }
}());

And then finally change your css selectors to only match if the class touchok is on body.

I've not tested it with your stuff, but it would take away the hover on the a and that should make sure the double tab is never triggered.

eg.:

.hoverok a:hover {
  color:red;
}
  • 1
    Hover and touch aren’t exclusive, E.g. a laptop with a touchscreen and a mouse. Your script would result in a bad user experience on such devices. – ausi May 18 '15 at 07:56
  • Actually it only stops the hover effects once touch is actually used on the page by the user. So yes it'll act as if it's got no hover once the user is using touch. –  May 18 '15 at 10:47
  • Can't edit the comment anymore ... So yes it'll act as if it's got no hover once the user is using touch and will continue to do so on that page till they navigate away. It's relatively easy to add a timer to re-enable the hover effect (simple put back the class on the body) if no touch events took place for a small amount of time if you have content where people would actually switch from having used touch back to a mouse - but that's not happening with any user I've ever seen: either they're pawing the screen or either they're not. –  May 18 '15 at 10:56
  • I don’t think it’s a good idea to turn hover styles off for touchscreens. What if tomorrow a new device enters the market which has a touchscreen with support for `:hover`? Hover will be detectable in the future via `window.matchMedia('(any-hover: hover)')`, but for now we shouldn’t turn hover styles off. – ausi May 18 '15 at 12:11
  • Again: I'm not advocating that we "turn hover styles off for touchscreens". I'm merely turning superfluous hovers off that create real trouble on real touch devices ONCE the user is actually using touch (as in: they are smudging the screen, not they might, but they are.). –  May 19 '15 at 12:55
  • 1
    Tomorrow? Today! It's called Galaxy Note (and similar from Asus, HTC, etc, using the wacom pen + sensor). It detects the pen from a certain distance and hover is very useful here. Simply using max/min-width media queries provides the desirable behavior only for iPhone users. Maybe this javascript helps, because pure CSS does not. – rdlu Oct 24 '16 at 13:08
-1

I faced a similar issue when toggling display state of 2 images upon hover:

.element__color-primary:hover { display: none; }
.element__color-secondary:hover { display: block; }

Android devices worked fine.

Using media queries to apply hover effects only on larger screens was a quick and simple fix that I have implemented. In my case, doing so did not deteriorate user experience.

Jakub Wawszczyk
  • 377
  • 3
  • 11
  • I think in your case the browser works as intended, because `display: none` and `display: block` are considered a “content change”. This is documented on [developer.apple.com](https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW4). – ausi Sep 06 '16 at 12:02