Thursday, January 20, 2011

:hover is dead Jim.

The :hover pseudo-class is dead, it just hasn't fallen over yet. In fact it's not just dead, it was murdered. Killed by the touch interface.

I'm not exactly clear on when :hover was created or by whom. It was included in the May 1998 CSS2 specification and I believe Microsoft's Internet Explorer 5.5 beta in December 1999 was the first browser to implement it (but only for the "a" tag, which is still true today). I've seen reference to Microsoft having invented it and contributing it the CSS specification. It was subsequently supported in other browsers.

If you think about it the :hover pseudo-class is actually a pretty amazing little bit of shorthand. It tracks the pointer position when it is over the coordinates of the element to which it is applied and can perform actions based on that detection. Take something as simple as the very common image rollover on a button - with :hover it can be accomplished in one line of code that single line could create the rollover effect for EVERY button on the page. Try to accomplish the same thing with Javascript and you'd have to give unique IDs to each button, create custom functions that could be called from those buttons that defined variables for the height, width, and top+left coordinates of the button itself and then another function to track the mouse coordinates and yet another function that performed the swap-out on that button, but only if the mouse coordinates were within the same area defined for that particular button. That fact that :hover can accomplish all that in one line of code is frankly. . .beautiful.


Deano said...

Thanks for the post. This was the first post I could find that really addressed this issue. I am a little stumped though. Why don't mobile devices support the :hover pseudo-class? Is it absolutely necessary to drop support? It seems a little arrogant if not cheezy that manufacturers are choosing to do this.

OffWorld Girl said...

@Deano - on a touch device you're either touching something or you're not. the :hover pseudo-class is like saying "I might press this, but maybe I won't." There's really no way for a touch device to know where your finger is unless you're touching the screen, which is like an onclick/mousedown event, not hover.

Normally on a touch device the :active pseudo-class is the one that gets triggered by the mousedown/touchstart event. I rarely use "down" states in my image rollovers because on a desktop system users have to hold the mouse button down on the object to see it and most people just do a quick click and it switches so fast you don't even see it. So you can also assign the same styles/image as :hover to the :active pseudo-class and then, when someone on a touch device presses the button/object/link it will show them the same thing desktop users see on :hover (and also on :active "mousedown" but they won't notice because you can't be :active without also triggering :hover first).

So that's a real simple fix! Just assign the same rollover/style you use for :hover to the :active state and you've got touch devices covered too.

A lot of UI designers have long argued "hover effects" are actually bad UI design in the first place. That it should be obvious what is clickable or interactive without you having to move a pointer over the thing first. Something to think about.

OffWorld Girl said...

To clarify something, on touch devices they assume most web content is NOT touch enabled, so when you touch an interactive element it triggers "fake" mouse events (onclick, mousedown, mouseup, and mousemove). So for most websites you don't even need to THINK about touch devices, because they'll be faking mouse actions (with the obvioius exception of hovering). That is the default touch device behavior.

The only time you have to make special accommodations for touch devices is i you've prevented the default action - in which case the fake mouse events don't happen. That's when you have to code event listeners for ontouchstart, ontouchend, etc.