What this success criterion requires
Success Criterion 2.4.7 of WCAG 2.2 (Level AA) requires that whenever keyboard focus moves, there is a visible indicator on the focused element. WCAG 2.2 also adds Success Criterion 2.4.11 Focus Not Obscured (Minimum) at Level AA: the focused element must not be entirely hidden by author-created overlays. The two are usually addressed together.
Why it matters
Keyboard, switch device, and voice-control users have no analogue of a
mouse pointer. The focus ring is their only way to know where they are
on the page. A site that suppresses focus indicators with
outline: none is unusable for these users — they must guess which of
fifty buttons is currently active.
What a passing implementation looks like for end users
Pressing Tab moves focus to the next interactive element. The user sees a clear, contrasting outline or change of style on that element. The outline is perceivable against the background under the same lighting conditions that ordinary text must be perceivable under (see /wcag/2.2/aa/1.4.3). The outline is not entirely covered by a sticky header, modal scrim, or autocomplete dropdown.
A passing implementation does not require the use of the default UA focus ring. Custom focus styles are explicitly permitted. They must, however, be at least as perceivable as the default and reliable across all interactive elements, including custom widgets.
Authoring patterns
The :focus-visible pseudo-class is the recommended primitive. It
matches when the user agent determines that focus is being shown for a
keyboard-style reason (Tab, arrow keys, Enter, F-keys), and not when
focus is set by a mouse click on a button. Use :focus-visible rather
than :focus to avoid showing the ring on click events while still
showing it for keyboard users:
:where(button, a, [role="button"], input, select, textarea):focus-visible {
outline: 3px solid var(--c-brand-primary);
outline-offset: 2px;
border-radius: 4px;
}
Custom controls (anything with tabindex or a non-default role) must
also receive a :focus-visible style. WCAG 2.2 added Success Criterion
2.4.13 Focus Appearance at Level AAA, which gives a numeric size
and contrast for the indicator (at least a 2 CSS-pixel-thick perimeter
with 3:1 contrast against the unfocused state). Many sites adopt the
AAA target as their AA baseline.
Browser engine support
:focus-visible reached interoperable support across Chromium (Blink),
WebKit, and Gecko in 2022. The heuristics for when the pseudo-class
matches differ slightly between engines but converge on Tab, Enter,
arrow keys, and programmatic focus. Touch focus in WebKit is treated
as non-keyboard for :focus-visible, matching Chromium and Gecko.
Common pitfalls
outline: nonewithout replacement. This is the most common failure mode. If a design system removes the UA outline, it must ship a custom one for every interactive selector.- Outline obscured by sticky header. When focus moves to an item
in a long list, the focused item may be scrolled under a sticky
header. Use
scroll-margin-block-startto add room for the header. - Modal scrim covers focused element. Move focus into the modal on open and trap it there until close.
box-shadowonly. A box-shadow indicator is permitted, but ensure it is rendered above sibling elements; it is otherwise clipped byoverflow: hidden.- Skip-link hidden off-screen but never made visible on focus.
The skip link must reveal itself in
:focus-visible.
Verification
Engine accessibility panels in Chromium, WebKit, and Gecko can step
through the keyboard tab order and report missing focus indicators.
A human verifier should also Tab through every page once with the
mouse parked, simulating keyboard-only operation. Automated checkers
can detect outline: none without a replacement, but cannot judge
whether a custom indicator is sufficiently perceivable.