interactionintermediate

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.

❌ No focus ring — inaccessible
⚠ Default — visible but not branded
✓ Custom focus ring — best

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.

Common mistakes

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.