Focus Visible
A CSS pseudo-class that targets elements with keyboard focus but not mouse or touch focus.
Plain English
Focus-visible solves a long-standing design problem: keyboard users need a visible ring around the focused element to navigate, but mouse users get an ugly ring on every click. The :focus-visible pseudo-class shows the ring only when it matters — when you are using a keyboard. This means designers can stop removing outline: none (which broke keyboard navigation) and instead style a beautiful, visible focus ring that only appears for keyboard and screen reader users.
Technical
:focus-visible is triggered when the browser determines keyboard navigation is in use. Mouse clicks on buttons and inputs do NOT trigger :focus-visible in most browsers; keyboard Tab, arrow keys, and focus() called from scripts DO trigger it. To use: replace :focus { outline } with :focus-visible { outline }. The global default should be :focus-visible { outline: 2px solid accent; outline-offset: 2px; }. :focus-within targets a parent when any child has focus — useful for form field highlighting.
Live Demo
Focus Ring Comparison
Click each button to simulate keyboard focus state.
focus-visible only shows the ring for keyboard nav, not mouse clicks.
Usage
✓ Good usage
Set :focus-visible { outline: 2px solid #2563EB; outline-offset: 2px; } globally, giving keyboard users a clear indicator without cluttering mouse-user interactions.
✗ Bad usage
a:focus, button:focus { outline: none } with no replacement — makes keyboard navigation completely invisible.
Recommended values
- Global focus ring: 2px solid accent-500, outline-offset: 2px
- Rounded elements: simulate rounded ring with box-shadow: 0 0 0 2px bg, 0 0 0 4px accent
- Dark backgrounds: use accent or white ring with sufficient contrast
- Minimum contrast: 3:1 between ring and adjacent background (WCAG 2.4.11)
- Never remove focus indicators — replace with a custom ring if the default is ugly
Common mistakes
- Using :focus instead of :focus-visible — the ring appears on mouse clicks, designers remove it, keyboard nav breaks.
- Removing focus styles without a replacement — critical accessibility failure.
- Low-contrast focus ring — technically present but not visible enough.
AI Prompt Example
Copy this into Claude, Cursor, Bolt, or v0.
Apply globally: :focus-visible { outline: 2px solid #2563EB; outline-offset: 2px; border-radius: 4px; }. For rounded buttons, simulate with box-shadow: 0 0 0 2px white, 0 0 0 4px #2563EB. Never remove focus styles — only replace them.