Keyboard-only focus styling

:focus-visible

Baseline widely available
  • Chrome86
  • Edge86
  • Firefox85
  • Safari15.4

Features it needs

The focus-visible polyfill watches whether the last interaction was a keyboard press or a pointer click, then toggles a class so a mouse click doesn't leave a focus ring behind. The CSS pseudo-class :focus-visible does that same judgment call natively: the browser decides whether focus came from something that benefits from a visible ring, no JavaScript class-toggling required.

When this applies

Showing a focus ring only for keyboard or other non-pointer focus, not for a mouse click.

The native approach

button:focus {
  outline: none;
}
button:focus-visible {
  outline: 2px solid var(--accent);
}

MDN reference

When the dependency is still right

An answer that always says "the platform covers it" is worse than no answer. These are the cases where this one does not hold.

  • You need to support Internet Explorer or a browser old enough to predate :focus-visible, which the polyfill's JS-based heuristic still covers.
  • You need the exact same heuristic across every browser version, including ones that shipped :focus-visible before the spec's behavior settled. Small heuristic differences existed early on.

Signs it was hand-rolled

No package is involved in any of these, so nothing would match in a package.json. If the code looks like one of them, this rule applies anyway, and the conditions above still decide.

  • listening for keydown and mousedown on the document to track whether the last input was a keyboard
  • toggling a class such as using-keyboard on the body so focus rings can be shown conditionally

Packages this covers