CSS :focus-visible - Keyboard-Only Focus Styles
Use :focus-visible to show focus indicators only for keyboard users. Improve accessibility without cluttering the UI for mouse users. Browser support and fallback strategies.
Detailed Explanation
The :focus-visible Pseudo-class
The :focus-visible pseudo-class matches when an element has focus and the browser determines that focus should be visually indicated. In practice, this means it triggers on keyboard navigation but not on mouse clicks.
The Problem :focus-visible Solves
Using :focus alone shows focus rings for both keyboard and mouse users:
/* This shows outlines even when clicking with a mouse */
button:focus {
outline: 2px solid blue;
}
Designers often want to remove these outlines for mouse users, but doing so harms accessibility:
/* DON'T DO THIS — breaks keyboard accessibility */
button:focus {
outline: none;
}
The Solution
/* Show focus ring only for keyboard navigation */
button:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
/* Remove default outline for mouse clicks */
button:focus:not(:focus-visible) {
outline: none;
}
When Does :focus-visible Apply?
- Tab key navigation — always triggers
- Arrow keys in form controls — triggers
- Mouse click on a button — does NOT trigger
- Mouse click on an input — DOES trigger (inputs always show focus)
- Programmatic focus via
element.focus()— depends on context
Modern Approach
Many browsers now apply :focus-visible behavior to their default focus styles. You can simplify:
/* Modern: style focus-visible directly */
:focus-visible {
outline: 2px solid var(--focus-color, #3b82f6);
outline-offset: 2px;
}
Browser Support
Chrome 86+, Firefox 85+, Safari 15.4+. For older browsers, use the focus-visible polyfill.
Use Case
The :focus-visible selector is essential for building accessible web applications that also have polished visual design. WCAG 2.1 AA requires visible focus indicators, but showing focus rings on every mouse click degrades the visual experience. :focus-visible provides the perfect balance, and it is now a best practice in all modern CSS frameworks and design systems.