CSS magic, pt. 1: Prevent CSS hover on touch devices

Per Jonsson
2 min readApr 22, 2018

--

Solving problems within their own domain

JavaScript shouldn’t be the first resort when resolving styling issues in 2018, still we see a lot of it. Perhaps because old habits persist, but they needn’t, because:

  1. The specs have become quite capable
  2. The CSS tooling has become quite capable

Let me give an example.

The problem

I encountered a problem where a responsive web app — intended to behave differently based on device — triggered undesired hover effects when browsing on a mobile device (yes, some mobile browsers support hover).

The Dirty Solution

The most upvoted answer on Stack Overflow directly suggests a “quick’n’dirty” solution using JavaScript. Further down, someone correctly points out that CSS supports pointing device adaptation, and the support is rather overwhelming.

The Clean Solution

So it turns out, we can solve the problem without using another domain by utilizing CSS media queries and the pointer feature. To quote MDN:

The pointer CSS @media media feature can be used to apply styles based on whether the user’s primary input mechanism is a pointing device, and if so, how accurate it is.

Elaborating on one of the suggestions a support table was compiled:

So, it turns out that no desktop browser recognizes pointer: coarse, while all mobile browsers do.

Results

Using reversed logic, a media query can be constructed that prevents a mobile browser from triggering hover effects at all.

HTML

<div>
<!-- Should not trigger on touch device -->
<button>Hover me without touching please</button>
</div>

Sass Mixin

@mixin hover-supported {        @media not all and (pointer: coarse) {
&:hover {
@content;
}
}
}
button {
background-color:gray;
@include hover-supported() {
background-color:white;
}
}

Compiled CSS

button {
background-color: gray;
}
@media not all and (pointer: coarse) {
button:hover {
background-color: white;
}
}

Didn’t have to make it more complicated than that.

Update (2018–12–09)

As of 2018–08–23, and pointed out by Matthew Perry in a comment, this technique no longer works with Firefox.

Demo

Try it out here! https://codepen.io/programmerper/pen/XqmWGP. Also described in this gist.

--

--

Responses (4)