Why and how to not use hover styles on touch devices
January 26th, 2013Buttons that show only on hovering over an area with the mouse are a great (if controversial) way to declutter user interfaces on traditional desktops where users have a mouse or trackpad. On mobile devices (phones and tablets), users use their finger instead, and there’s no more way to just hover over an element on a webpage—hovering and “clicking” are invoked by the same action: tapping.
Mobile browsers solve this issue by having the first tap invoking the hover style of an element and, if applicable, the second tap invoking any “click” events. Because of the need to discern swipes and taps, there’s a noticeable delay in browser response time. What this adds up to is that when you have both a :hover
style and a onclick
event on, say, a contained button in the :hover
area, users end up spending the better part of a second trying to invoke the “click” on the button (300ms for the hover tap, 300ms for the click tap, and extra time for lifting the finger in-between).
The easiest way to deal with this is simple: don’t use :hover
on touch-enabled devices.
Here’s one way I solved this in Freckle Time Tracking:
- I use Zepto’s detect module to see if I’m on a tablet or phone (you can use this module independently of Zepto, it doesn’t have dependencies on it).
- If it’s a tablet or phone, I add a “no-hover” CSS class to the
BODY
element - I disable any
:hover
styles with selectors that usebody.no-hover ...
. You actually don’t have to redefine the:hover
rule, just make sure the normal rule and the:hover
rule contain the same CSS property settings (likevisibility:visible
)
Now, my reason for not feature-testing (sue me!) for support of touch events and instead using browser sniffing is that 1) historically detection of touch events has been unreliable, 2) there are hybrid browsers and devices that support both touch and normal mouse events, and 3) it’s faster.
Update Jan 26, 7:50pm ET: Here are two more variants on this, the first one is from Thijs van der Vossen, and is a short JavaScript snippet that you can inline in your HEAD
element. It adds multiple classes to HTML
, depending on the environment it’s run in. The second variation is a CoffeeScript function to automatically remove :hover rules from Mislav Marohnić (assumes a modern, properly DOM-compatible browser).