Hover states with purpose

Hover is the only interface state that half your users will never see. It exists on pointer devices, evaporates on touch, and is invisible to keyboards, switches, and screen readers alike. And yet entire design systems are quietly built on top of it — menus that only open on hover, actions that only appear on hover, affordances that only announce themselves when a cursor happens to pass over them.

That's the scandal. But there's a quieter opportunity on the other side: hover, precisely because it's optional, is the perfect place for a layer of teaching — the confirmations, previews, and hints that make an interface feel considered without ever being load-bearing. The difference between a hover state that teaches and one that decorates is the difference between craft and noise. Here's the taxonomy we design against.

The one law: hover is a bonus, never a requirement

Everything else in this article follows from a single rule: no information or action may exist only on hover. Content hidden behind hover is content that doesn't exist for touch users, keyboard users, and anyone on a device you forgot to test. Actions that appear on hover are invisible until discovered — a pattern that tests terribly every single time it's measured honestly.

The classic offenders, still found in audits with depressing regularity:

  • Hidden-by-default icon buttons on table rows and cards ("edit", "delete" appear on row hover). On a touchscreen they either never appear or appear after a first tap that did something else. The fix is not cleverer hover; it's either always-visible actions or an explicit overflow menu that's a real, focusable control.
  • Hover-only navigation — mega menus with no click path. We covered the mobile fallout in navigation that survives the 375px test; the short version is that if a menu can only open on hover, around half your traffic navigates by luck.
  • Tooltips as the only label. An icon whose meaning exists only inside a hover tooltip is an icon with no meaning. If the label matters, render it or make the tooltip a genuinely accessible disclosure — and even then, ask why the label isn't just visible.

Once the law is accepted, hover relaxes into its proper role: the frosting, not the cake. And frosting turns out to have a real job to do.

What hover is genuinely good for

Four legitimate purposes, in descending order of value:

1. Confirming interactivity before the click. The foundational job. A cursor change, a colour shift, an underline appearing — these answer "can I click this?" before the user commits. The cost of a missed confirmation is hesitation or a misclick; the cost of a false one is a dead click and a small betrayal. Both directions matter. Anything that looks interactive but isn't will collect rage-clicks; anything interactive that doesn't look it will collect dust.

2. Previewing the destination. Hover can show what a click will do before it's done: the card lifting slightly to promise it opens, the chart segment highlighting to promise it can be isolated, the link's arrow nudging right to say "this goes somewhere". Previews reduce commitment anxiety, which is the entire emotional economics of browsing an unfamiliar site. Our related-content work found that cards behaving like links — whole-card hit areas with a visible hover response — outperformed "read more" text links by a wide margin.

3. Revealing reversible detail. Timing on a video thumbnail, the second value in a metric ("2,431 this week" → "+18% vs last"), a truncated label's full text. The key word is reversible: this is detail that's nice to have, available elsewhere, never the only path to the meaning.

4. Delight, deliberately dosed. The magnetic button, the wordmark that blooms, the cursor that rings. Fine — even valuable, as brand — provided it follows the micro-interaction taxonomy: 160–200ms, ease-out, no layout shift, silent on touch, and absent under reduced motion. Delight that costs frames or accessibility is just an expense.

The anatomy of a good hover state

When we spec a hover state in a design system, four properties get decided explicitly — if your tokens don't name these, the hover layer will drift into inconsistency within a quarter:

Property. What changes: background, border, underline thickness, transform, shadow, arrow position. Pick one or two. A hover state that changes four properties reads as flinching, not responding.

Magnitude. How far it travels. Our defaults: background shifts one tint step up or down in the ramp; transforms move 2–4px maximum; underline grows from 1px to 2px. If you can perceive the change only by A/B-ing screenshots, it's too subtle; if you notice it across the room, it's honey-I-shrunk-the-interface.

Timing. In fast, out with a hair of patience. Transition in around 120–160ms, out at 200–240ms — the slightly slower exit prevents flicker when a pointer sweeps across a row of links, and it reads as composure. Instant-in/instant-out is technically correct and feels like a machine from 2009; long eases feel like the page is made of porridge.

Scope. What the state applies to — and the answer is increasingly "the whole interactive region". On cards, rows, and list items, hover the container, not just the text link inside it. The hover surface and the click surface should be the same surface, always. Mismatched surfaces — a card that lights up but only has a clickable title — are a trap you built on purpose.

Focus parity: the twin rule

Every hover state ships with a sibling question: what does keyboard focus look like here? The relationship between the two is one of the most misunderstood corners of CSS, so let us be precise:

  • Focus is a requirement, hover is a bonus. Focus must be perceivable at WCAG contrast against its surroundings; hover just has to be noticeable. They are not interchangeable, and styling them identically usually means both are wrong — focus needs to survive on top of any hover background, and hover shouldn't be as loud as focus needs to be.
  • :focus-visible is the modern default. Show the strong focus ring for keyboard navigation, skip it for mouse clicks. We wrote the full argument in focus-visible: designing the ring, not removing it — the summary is that the ring is a designed element with its own tokens, not a browser default to suppress.
  • The states stack. A focused element being hovered needs both treatments to compose without cancelling — define the combined state explicitly or one will clobber the other in specificity roulette. This is exactly the class of thing our engineers encode once and test forever in keyboard-first interface engineering.

A practical parity audit we run on every component library: tab through the page with your eyes closed-ish, then sweep a pointer across it. Every element that reacts to one should react to the other, appropriately. Any element that reacts to neither had better be inert.

Touch honesty: design for the tap, test on the glass

On touch devices the first tap is the hover — which sounds elegant until you catalogue what it breaks. Hover-reveal menus require a tap to open and a second to navigate (two taps disguised as one gesture). Hover tooltips fire and stick awkwardly. Hover-lift on cards flashes as you scroll past with a thumb.

Our touch rules:

  1. Design the touch state first for any interactive surface. If the component only makes sense with hover, redesign the component.
  2. Never let :hover styles stick on touch. The tap-and-stuck-hover bug (styles lingering after the finger lifts) is solved with @media (hover: hover) — gate true hover effects behind the media query so touch never inherits them. This one wrapper eliminates a whole class of "why is this button stuck" bug reports.
  3. Active states exist. :active on touch is the real "I'm pressing this" feedback, and it's chronically under-designed. A 10% darken on press, 100ms, does more for perceived quality on a phone than any hover ever could.

Where restraint pays: a few strong opinions

Some positions we've settled after enough audits:

Navigation links: underline on hover, duration fast, and the underline is already there for the current page. Consistency between "you could go here" and "you are here" states makes the chrome feel like one system instead of two.

Data visualisations: hover is where the precision lives. The axis gives you the shape; hover gives you the number. But the number must also be reachable by keyboard (focus the point) and must not be the only place a key figure exists — pull the headline number into the caption.

Destructive actions: hover should warn, not surprise. The delete button turning clay-red on hover is good theatre, but the safety belongs in the confirm step, not the colour. Never let hover be the first signal that an action is irreversible.

Images: hover zoom is a cliché with one legitimate use. Product and portfolio imagery earns a subtle scale (1.02–1.04, slow ease) because it mimics leaning in. Everywhere else, zooming photographs on hover is the visual equivalent of a stock handshake.

Key takeaways

  • The one law: nothing exists only on hover. Hover teaches, previews, and confirms — it never gates.
  • Purposeful hover has four jobs: confirm interactivity, preview the destination, reveal reversible detail, dose delight. Everything else is noise.
  • Spec property, magnitude, timing and scope for every hover state, or the system will drift.
  • Focus and hover are twins, not clones: :focus-visible for keyboards, composed stacked states, parity audits on every component.
  • On touch, gate hover behind @media (hover: hover), design the tap first, and give :active the love hover gets.
  • Fast in, slightly slower out, 2–4px of travel, one tint step of colour. Hover should feel like the interface noticing you, not performing for you.

Frequently asked questions

Should interactive elements always change colour on hover?

No — they should always respond, but response isn't limited to colour. Underline growth, arrow movement, elevation, and cursor changes all confirm interactivity, and two subtle responses together read better than one loud one. Colour-only responses also fail users who can't perceive the hue difference, so pair colour with a shape or position change.

Are cursor changes (pointer, grab, etc.) enough of a hover state?

The pointer cursor is the floor, not the state. It answers "is this clickable?" at the resolution of a line of text. For anything card-sized or larger, the cursor alone is under-communicating — users routinely miss pointer changes. Layer a visual response on the element itself.

How do we handle hover on elements inside links or buttons?

One interactive element per region. Nested interactives (a button inside a link's hit area) are invalid HTML, a keyboard trap, and a hover-state nightmare — the nested element's hover fighting the parent's. If you need two actions, give each its own region, clearly divided.

Do hover states need to be in the design tokens?

The values do — the tint steps, durations, and easings should be tokens shared by hover, focus, and active. The specific per-component recipe (which properties, what magnitude) belongs in the component spec. Tokens without recipes drift; recipes without tokens can't be themed.


Keep reading