Jacob Padilla

The Most Underused CSS Media Queries: Hover & Any-Hover

Today I want to talk about my favorite media queries in CSS, hover and any-hover, which let you detect if a user is able to hover over elements on your website. Besides the width-based media queries, to help with responsive design, the hover media queries have been by far the most useful for me. In this article, I'm going to go over two extremely useful ways that I use the hover media queries, but first, let's talk about how they actually work.

What Do They Even Do?

Starting with hover, this media query is used to check if the primary input mechanism of a user's device can hover over elements. Generally, a computer's primary input mechanism is a mouse or trackpad, which controls a cursor on a screen; since cursors can move over elements, they are able to hover over things. However, touchscreens have a primary input of touch, which can't really hover over elements...

While hover is the one that I generally use, there is also any-hover, which looks at all of the currently available input methods and tells you if any of them can hover over things. An example where this would be useful is if a person is using an iPad with a Bluetooth mouse connected to it. Since the primary input of an iPad is touch, hover would fail the test, but any-hover would pass the test because it looks at all input methods, and a mouse, which on an iPad will appear as a tiny circle on the screen, can hover over elements.

Both hover and any-hover have two modes: hover, meaning that the user can hover over elements, and none, signaling that they can't. Here's what the syntax looks like with hover; for any-hover, swap hover with any-hover.

@media (hover: hover) {
    /* The user can hover - generally with a mouse cursor */
}

@media (hover: none) {
    /* No hovering available - generally a touchscreen */
}

Why You Need to Start Using Them

Now, let's go over the main use cases for the hover media query! I'm going to use hover for the examples, but they will all work with any-hover.

Fix Glitchy Hovering on Touchscreens

One of the most useful ways of using hover is to fix glitchy, also called “sticky”, hover effects on your website. Sticky hovering is caused when there's a hover animation on an element, but when tapping on it with a touchscreen, the :hover pseudo-class styling, which may make the element darker or show an underline, sticks and never goes away.

An example of this issue (that's solved with hover) are my links which change background color when hovering over them. When a user is able to hover, the text gets darker, and a background appears under the link, which helps the links be more visible and thus more accessible.

Here's the code I wrote for the links:

Some HTML:

<a class="blue-link" href="a-link-here" target="_blank">Link Text</a>

The link styling:

.blue-link {
    text-decoration: none;
    cursor: pointer;
    color: var(--second-color);

    background-image: linear-gradient(var(--second-color-opaque), var(--second-color-opaque));
    background-size: 100% 0px;
    background-position: bottom;
    background-repeat: no-repeat;
    
    /* 1px padding around background */
    background-clip: border-box;
    padding: 1px;
    margin: -1px;

    transition: background-size 150ms;
}

@media (hover: hover) {
    .blue-link:hover {
        color: var(--constant-light-mode-second-color-dark);
        background-size: 100% 100%;
    }
}

Here's a video of the link without the hover media query wrapped around the :hover pseudo-class - I'm using Inspect Elements to mimic a touchscreen:


The link background sticks and doesn't go away until tapping somewhere else on the screen. But, here's what it looks like with the hover media query fix on a touchscreen:


And you can also see that the hover effect still works as expected with a cursor:


Display Content on Touchscreens

The other way that I like to use hover is to automatically show users extra information that would normally only be seen by hovering over an element. Let's say we have some sort of icon/tooltip that, when hovered over, displays additional information about said icon. On a touchscreen, we may want this information to always be visible since there's no hover capability. Here's how we can achieve that:

<div class="info-icon">An icon/button/image</div>
<div class="info-tooltip">Some text explaining what the icon does</div>
.info-tooltip {
    display: none;
    background-color: lightgray;
}

.info-icon:hover + .info-tooltip {
    display: inline-block;
}

@media (hover: none) {
    .info-tooltip {
        display: inline-block;
    }
}

In this snippet, the tooltip is initially set to display: none; and becomes visible when the user hovers over the info icon. However, it's shown immediately if the browser (probably a phone) doesn't support hovering. Here's what the result looks like:


Final Thoughts

Both hover and any-hover are great ways to ensure that your site works on all types of devices, all while improving users' experiences. The examples I showed are the most common ways that I use them, but there are basically an endless number of creative use cases for them. Make sure to use them next time you're writing some responsive CSS!