Last Updated: September 29, 2021
· johnbender

Tap vs. Click: Death by Ignorance

The mobile web can be a weird place at times. One of the most important details to keep in mind when building a great user experience is how tap and click work, and how they interact (hint: poorly).

Supporting Click

Mobile browsers that support touch event bindings (eg, Webkit) also have to support click bindings on the same element, otherwise webpages built for the desktop would be completely useless on mobile browsers. So for every tap on a mobile web page a click is fired right along with it.


Initially this seems like a trivial detail and that we might just bind to click and be done with the whole discussion. Unfortunately there exists a 300ms (+/-) delay between the touchstart and click events to allow for scrolling, cancelling, and other interactions. This means that if you just bind to click, your user interactions are going to feel really sluggish.

Assuming you care about that sort of thing the next best solution would be to normalize by grabbing the first event and cancelling the second, but before you run off to do that you should know that the click event doesn't always fire on the same object as the touch event. Mobile browsers use complex heuristics to determine touch and click targets. In some browsers if you click near the border of an element the click will fire on a different target.

jQuery Mobile has addressed these problems (in so far as they can be addressed) with the vmouse plugin. It gives you virtual mouse events that will handle both mobile and desktop browsers to get your callbacks executing as quickly as possible. You can get your hands on it by cloning the repo and removing the amd define wrapper.

update We've updated the deps to allow the downloading of vmouse by itself from the builder: simply select "Latest" or the upcoming alpha and you'll be able to choose vmouse by itself.

Content Shift

The final thing to keep in mind, which can't really be solved in JavaScript, is a touch event triggered content shift. That is, if you shift content out from under the location of the touch event before the click event fires, the click event will fire on whatever is underneath it. If you get nothing else from this just remember, don't shift content on a touch event.


Finally, a note about standards. Specifically, the w3c's touch event standard is stalled thanks to patent issues which means things will get worse with Microsoft introducing its own standard (MSPointer). We should all get used to dealing with the disparity between the two event structures because it's going to be this way for a while.


Lots more reading from my friend Kin Blas:

2 Responses
Add your response

I think I have the 'Shift Content' issue on my iPad (phonegap app), when typing (using the virtual keyboard) in a textfield. To hide the keyboard I click above the keyboard. But when the keyboard hides, the content moves down, and the element belonging to the place where I clicked gets clicked :(
Is there a solution for this ?

over 1 year ago ·

You can do a event.preventDefault() during the touchstart event to cancel the click events.

over 1 year ago ·