Robert Leeper <- Thoughts

Accessible :hover styles

#css #accessibility

Long ago, I wrote that you can't touch :hover effects, so it's best to focus on other ways to communicate possible interactions to users. In short, hover effects are mostly limited to desktop browsers, which means a lot of your users may be left unsure of how to navigate.

While the advice in that article is still worth considering, there are now other options that weren't available when I first wrote about the topic.

There are plenty of reasons for adding hover effects to websites by making use of the :hover pseudo-selector. Sometimes you don’t want links to have an underline right away but you want them to show on hover…

a { text-decoration: none; }
a:hover { text-decoration: underline; }

That works but we’ve landed on the problem. For all practical purposes, mobile users won’t ever see the underline and that can have negative effects on usability.

Instead, let’s make it so links will have an underline by default. We can then add a media query to check if the browser supports :hover and if it does, we can progressively enhance from there. 

a { text-decoration: underline; }

@media (hover: hover) {
  a { text-decoration: none; }
  a:hover { text-decoration: underline; }
}

This gets us 80% of the way there, but there’s one more gotcha if you want to finish it properly: some Android devices mimic a hover input by way of a long-tap, so they claim to support :hover when, for our purposes, they don't. To address this you need one additional query: (pointer: fine)

a { text-decoration: underline; }

@media (hover: hover) and (pointer: fine) {
  a { text-decoration: none; }
  a:hover { text-decoration: underline; }
}

(pointer: fine) checks whether the the primary input method is fine like a mouse, or coarse as in touch input.

By combining hover and fine pointer queries, you can properly enhance your pages with hover effects where appropriate without completely chucking usability in the bin for the rest of your users.