How CSS Hover Works on Mobile Touch Screens
On mobile touch devices, the CSS :hover pseudo-class
behaves unpredictably because there is no persistent cursor to track
pointer position across the screen. Instead of triggering when a pointer
glides over an element, mobile operating systems adapt
:hover to touch events, often resulting in delayed clicks,
"sticky" hover states, or unexpected double-tap requirements.
Understanding this interaction model is critical for designing
responsive, touch-friendly web interfaces.
The Tap-to-Trigger Mechanism
Touchscreens do not continuously report coordinates prior to contact.
Consequently, mobile browsers only evaluate :hover when a
user physically touches the display.
When a user taps an element:
- The browser initiates a sequence of events:
touchstart,touchend, and then a syntheticmousemove/mouseover. - The CSS
:hoverstyles are applied instantly upon contact. - If the tapped element is a standard non-navigational element (such
as a
<div>with custom styles), the:hoverstate remains active even after the finger lifts. This phenomenon is known as the "sticky hover" effect. The state persists until the user taps a different interactive element on the page.
The Double-Tap Phenomenon on Links
Mobile browsers, particularly iOS Safari, employ heuristics to
prevent broken interactions on links that rely on hover menus or
tooltips. If an anchor tag (<a>) or button changes
visibility or display properties on :hover (such as
displaying a previously hidden dropdown menu), the browser alters its
standard click behavior:
- First Tap: Triggers the
:hoverand:focusstates, allowing the user to view the newly revealed content. The underlying link is not followed. - Second Tap: Dispatches the actual
clickevent, following the link or triggering the primary action.
While this allows desktop dropdown menus to function on mobile without crashing, it can frustrate users who expect a standard link to navigate immediately.
The Absence of "Unhover"
Desktop environments rely on mouseout and
mouseleave events to strip away hover styles when the
pointer departs. On touch screens, there is no spatial concept of moving
away from an element while maintaining screen contact. Because
there is no natural "unhover" trigger, elements designed to expand,
change color, or display supplementary text will retain those visual
alterations until another part of the document receives a tap.
Solving Hover Issues with CSS Media Queries
Modern CSS provides Interaction Media Features to separate pointer capabilities from touch capabilities. Instead of relying on screen width, developers can target input mechanisms directly:
/* Apply hover styles only to devices that support true hovering */
@media (hover: hover) and (pointer: fine) {
.button:hover {
background-color: #0056b3;
transform: translateY(-2px);
}
}
/* Fallback or active styling for touch devices */
@media (hover: none) {
.button:active {
background-color: #004085;
}
}Using @media (hover: hover) ensures that hover states
are strictly reserved for users with mice, trackpads, or styluses. Touch
devices evaluate this query as false, completely bypassing the sticky
hover state and delivering an immediate, single-tap experience.