Focus Styles Without the Click Noise

Every interactive element should show a focus style — that’s how keyboard users know where they are. The problem is that a plain :focus rule also fires on mouse clicks, so many developers strip focus indicators entirely to avoid the visual “flash” after every click. That’s a serious accessibility regression.

The better approach is to show focus styles only when the keyboard is the input method. Lea Verou called this out years ago:

I’m gonna start blanket adding the following rule to all my stylesheets:

:focus:not(:focus-visible) { outline: none }

Gets rid of the annoying outline for mouse users but preserves it for keyboard users, and is ignored by browsers that don’t support :focus-visible.

— Lea Verou (@LeaVerou) September 28, 2018

That idea was behind a flag in Chrome at the time. Now, per the Chromium Blog, it ships unflagged. The browser team frames :focus-visible as a way to pair with :focus for input-dependent indicators:

By combining :focus-visible with :focus you can take things a step further and provide different focus styles depending on the user’s input device. This can be helpful if you want the focus indicator to depend on the precision of the input device:

/* Focusing the button with a keyboard will show a dashed black line. */
button:focus-visible {
  outline: 4px dashed black;
}
  
/* Focusing the button with a mouse, touch, or stylus will show a subtle drop shadow. */
button:focus:not(:focus-visible) {
  outline: none;
  box-shadow: 1px 1px 5px rgba(1, 1, 0, .7);
}

There’s no reason to scope those selectors to button — applying them globally works just as well.

What to Know Before You Switch

The selector’s matching behavior is heuristic-based. It isn’t a simple “is the keyboard being used?” check; the browser decides when a focus ring is appropriate based on context. In practice, you can largely trust it, but it’s worth reading the Chromium post to understand the nuances.

Firefox has long offered :-moz-focusring, but its behavior differs enough from :focus-visible that the Chromium team advises against using it if you want consistent results across browsers.

Practical Resources

  • The Chromium Blog post covers the heuristics behind the selector in detail.
  • Matthias Ott has written about the official polyfill and how to test :focus-visible styles in DevTools — there’s a dedicated checkbox for it.
  • CSS-Tricks previously covered keyboard-only focus styles, including Verou’s prediction that usage would “explode” once the feature shipped without a flag.
  • The CSS-Tricks almanac entry for :focus-visible contains additional reference material.