No Login Data Private Local Save

:focus‑visible vs :focus Demo - Online Accessible Outlines

8
0
0
0

:focus vs :focus-visible

Explore the key difference between :focus and :focus-visible — a critical distinction for building accessible, user-friendly interfaces.

Use Tab to navigate  |  Click with mouse to compare

Waiting for interaction...
Keyboard: 0  |  Mouse: 0
:focus Always visible outline

Outline appears regardless of how the element receives focus — mouse click, tap, or keyboard.

Custom focusable div (tabindex="0")
:focus-visible Keyboard-only outline

Outline appears only when the browser determines the user needs it — typically keyboard navigation.

Custom focusable div (tabindex="0")
Try this: Click each element with your mouse, then press Tab to navigate through both panels. Watch the right panel — outlines only appear during keyboard navigation!
Focus Event Log

Real-time log of focus events with detection method.

Interact with elements above to see events
CSS Implementation
/* ✅ Best Practice: Remove outline for mouse users, keep it for keyboard */
.your-element:focus {
  outline: none;           /* Reset default focus style */
}

.your-element:focus-visible {
  outline: 3px solid #0066ff;  /* Visible only for keyboard nav */
  outline-offset: 2px;
  border-radius: 4px;
}

/* 💡 Alternative: use :focus:not(:focus-visible) */
.your-element:focus:not(:focus-visible) {
  outline: none;
}
.your-element:focus-visible {
  outline: 3px solid #0066ff;
  outline-offset: 2px;
}
Broad Browser Support — Chrome 86+, Firefox 85+, Safari 15.4+, Edge 86+, Opera 72+. Check caniuse
Frequently Asked Questions

:focus matches an element any time it receives focus — whether via mouse click, touch tap, or keyboard navigation. :focus-visible only matches when the browser heuristically determines that the user is likely navigating via keyboard (or another non-pointer input method) and would benefit from a visible focus indicator. This allows developers to provide clear outlines for keyboard users while avoiding ugly focus rings for mouse clicks.

Using only :focus means focus outlines appear for all interactions — including mouse clicks on buttons, which most users find visually distracting. With :focus-visible, you can provide robust keyboard accessibility while maintaining a clean aesthetic for mouse/touch users. It solves the long-standing problem of developers resorting to :focus { outline: none; } (which harms accessibility) simply to avoid "ugly" focus rings on button clicks.

Browsers use internal heuristics based on the input modality that triggered the focus:

  • Keyboard navigation (Tab, Shift+Tab, arrow keys) → :focus-visible matches ✅
  • Mouse click on most elements → :focus-visible does NOT match ❌
  • Touch/pen input:focus-visible does NOT match ❌
  • JavaScript .focus() → depends on context; typically does NOT match unless called from a keyboard event handler
  • Text inputs and textareas → these always show :focus-visible regardless of input method (browsers treat text fields specially since users always need to see the caret position)

Yes, absolutely. WCAG Success Criterion 2.4.7 Focus Visible (Level AA) requires that any keyboard-operable UI component has a visible focus indicator. :focus-visible helps meet this requirement cleanly — it ensures keyboard users always see where they are on the page, without forcing visible outlines on mouse users. It also supports WCAG 2.4.13 Focus Appearance (Level AAA in WCAG 2.2), which specifies minimum contrast and thickness for focus indicators.

Yes! You can style :focus-visible just like any other pseudo-class. Common properties include outline, outline-offset, box-shadow, border-color, and border-radius. For the best accessibility, ensure the focus indicator has a minimum contrast ratio of 3:1 against adjacent colors and is at least 2px thick (WCAG 2.2 recommendation). Using outline-offset helps prevent the outline from blending into the element's edge.

Yes. As of 2024, :focus-visible is supported in all major browsers: Chrome 86+, Firefox 85+, Safari 15.4+, Edge 86+, Opera 72+, and Samsung Internet 14+. It's safe for production use. For legacy browser support (IE, very old Safari), you can use the official focus-visible polyfill from WICG, which adds a .focus-visible class to elements when the heuristic matches.

These three pseudo-classes serve different purposes:

  • :focus — matches the element that currently has focus (any input method)
  • :focus-visible — matches the focused element only when focus should be visibly indicated (keyboard heuristic)
  • :focus-within — matches an element that contains a focused descendant (useful for styling parent containers, form groups, or dropdown menus when any child is focused)

You can combine them for powerful patterns: e.g., .form-group:focus-within { border-color: blue; } highlights the entire form group when any input inside is focused.

Browsers make a deliberate exception for text input fields (<input type="text">, <textarea>, <select>, and elements with contenteditable). These always match :focus-visible because users always need to see where their text cursor (caret) is positioned — regardless of how they activated the field. This is part of the browser's heuristic: pointer-driven focus on a text field still warrants a visible indicator.