Accessibility
Focus indicator
A focus indicator is the visible change, usually an outline or ring, that shows which control currently has keyboard focus.
WCAG 2.4.7 Focus Visible requires one at Level AA, and when you style your own it needs 3:1 contrast against the colors beside it. Removing it with outline: none leaves sighted keyboard users unable to see where they are on the page.
At a glance
| Definition | The pixels that change to show a control is in its focused state, in WCAG's own words (2.4.7) |
| Required | 2.4.7 Focus Visible, Level AA: a visible indicator in at least one mode of operation, and it may not be time-limited |
| Contrast | 3:1 against adjacent colors when the author styles it (1.4.11, Level AA); the browser default is exempt from the ratio but must still be visible |
| Not hidden | A sticky header, footer or overlay may not fully cover the focused control (2.4.11, Level AA, new in WCAG 2.2) |
| Size, at AAA | At least a 2 CSS pixel perimeter around the component, changing by 3:1 between focused and unfocused (2.4.13, Level AAA) |
| In CSS | Style it on :focus-visible, so keyboard focus shows it and pointer clicks do not (MDN) |
| Found by | OverlayQA Accessibility Audit reports "No visible focus indicator" (2.4.7) when a control suppresses the default outline with no :focus rule; Auto Review flags interactive elements with no :focus rule in the stylesheet |
Why it matters
Every control is designed at rest and used in motion. A keyboard user moves through a page with Tab and can act only on a control they can see is focused, which is why WCAG makes the indicator a Level AA requirement (2.4.7) and, in version 2.2, adds that the focused control may not be entirely hidden behind author content such as a sticky header (2.4.11). Browsers once drew a ring on every click, authors removed it as ugly, and the fix has been available everywhere since March 2022: :focus-visible shows the indicator for keyboard focus and hides it for pointer clicks. MDN's summary is blunt: removing focus styles makes keyboard navigation inaccessible for sighted users.
How do you build a focus indicator that passes?
- 1. Keep the default until you have a replacement. Never ship outline: none on its own; styling outlines away without a visible alternative is WCAG failure F78.
- 2. Style :focus-visible, not :focus. The indicator then appears for keyboard focus and stays out of the way of mouse clicks, without changing when the browser decides focus should be shown (MDN).
- 3. Give it 3:1 against what is next to it. A gray ring at 2.3:1 on white is the W3C's own failing example (1.4.11). A two-color ring, white inside and dark outside, passes on light and dark backgrounds alike.
- 4. Make it thick enough to see. 2.4.13 is Level AAA, but its 2 CSS pixel perimeter is a sensible floor; a 1px hairline disappears on a high-density screen.
- 5. Keep it on screen. Check that sticky headers, cookie banners and chat widgets do not cover the focused control (2.4.11), and never move focus away the moment it arrives (failure F55).
- 6. Tab through the page. An indicator that exists in the stylesheet but is not visible on the screen fails; the only test that counts is pressing Tab and looking.
Examples
| Indicator | Verdict |
|---|---|
| Browser default ring, untouched | Passes 2.4.7; exempt from the 1.4.11 ratio |
| outline: none and nothing else | Fails 2.4.7 (F78) |
| 2px solid #3468F8 ring on white | Passes: 4.69:1 against white |
| Light gray ring on white | Fails 1.4.11 below 3:1; the W3C example is 2.3:1 |
| Ring that fades out after a moment | Fails 2.4.7: it must stay visible while focused |
| Focused button under a sticky footer | Fails 2.4.11 when the control is entirely hidden (F110) |
Common mistakes
- outline: none in the reset stylesheet. One line at the top of the cascade removes the indicator from every control on the site, and nothing looks broken to a mouse user.
- Styling :focus and then hiding it on click. The JavaScript workarounds for the mouse ring predate :focus-visible; replace them with the selector.
- A ring that only works on one background. A blue ring passes on white and vanishes on the blue primary button. Test the indicator on every surface it can land on.
- Matching the ring to the component. 1.4.11 asks for contrast against the adjacent colors, which includes the control itself, not only the page behind it.
- Trusting the stylesheet. Sticky headers, modals and focus moved by script all hide an indicator that passes in isolation. Judge it on the rendered page.
Frequently asked questions
Is a focus indicator required by WCAG?
Yes. Success criterion 2.4.7 Focus Visible, Level AA, requires that any keyboard-operable interface has a mode of operation where the keyboard focus indicator is visible. WCAG 2.2 adds 2.4.11, also Level AA, so the focused control may not be entirely hidden by content such as a sticky header, and 2.4.13 at Level AAA, which sets a minimum size and contrast for the indicator itself.
What is the difference between :focus and :focus-visible?
:focus matches whenever an element has focus, including after a mouse click. :focus-visible matches only when the browser decides the focus should be shown, which in practice means keyboard navigation. Styling the indicator on :focus-visible lets you change how it looks without changing when it appears, and it has been supported across browsers since March 2022.
How much contrast does a focus indicator need?
When you style it yourself, at least 3:1 against the adjacent colors under 1.4.11 Non-text Contrast, Level AA. The browser default indicator is exempt from the ratio as long as you have not modified it, but it must still be visible. At Level AAA, 2.4.13 Focus Appearance also asks for a 3:1 change between the focused and unfocused states over an area at least as large as a 2 CSS pixel perimeter.
Can I remove the focus outline for mouse users?
You can hide it for pointer clicks without removing it for keyboard users by styling :focus-visible instead of :focus; browsers then show the indicator only when their heuristics say it helps, which covers Tab navigation. Removing it outright with outline: none, with no visible alternative, fails 2.4.7 and is listed by the W3C as failure technique F78.
Sources: WCAG 2.2, 2.4.7 Focus Visible, WCAG 2.2, 2.4.11 Focus Not Obscured (Minimum), WCAG 2.2, 2.4.13 Focus Appearance, WCAG 2.2, 1.4.11 Non-text Contrast, MDN, :focus-visible.
Last updated October 22, 2026