The Most Underused CSS Media Queries: Hover & Any-Hover
Posted on
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!