Why You Shouldn't Remove the Focus Outline: A Practical Guide to WCAG 2.4.7 Focus Visible
Quietramp ·
Why You Shouldn’t Remove the Focus Outline: A Practical Guide to WCAG 2.4.7 Focus Visible
Quick answer: outline: none (or outline: 0) in a global CSS reset, applied to links, buttons,
and form fields with nothing put back in its place, is one of the most common accessibility failures
on the web — it removes the only visual signal a keyboard user has for where they currently are on
the page. WCAG 2.1.1 Keyboard Visible
(Success Criterion 2.4.7, Level AA) requires that “any keyboard operable user interface has a mode of
operation where the keyboard focus indicator is visible.” The Understanding document’s own named
failure example is exactly this pattern: “styling element outlines and borders in a way that removes
or renders non-visible the visual focus indicator.” The fix isn’t “never touch the default outline” —
it’s using the modern :focus-visible CSS pseudo-class
to style focus intentionally instead of deleting it outright.
This article covers technical accessibility practice, not legal advice — it explains what WCAG 2.1 AA (and WCAG 2.2, where noted) requires for focus indicators and how to meet it, not whether a specific implementation carries legal risk.
Why this keeps happening
Browsers ship a default focus ring — usually a blue or dotted outline — that appears around whatever link, button, or form field currently has keyboard focus. It’s not a design choice; every major browser has drawn one since the earliest days of the web, because it’s the only reliable way a keyboard-only user (or a mouse user who’s tabbing through a form) knows where they are.
That default ring also has a long history of looking, to a lot of designers, like a bug. It doesn’t match the site’s design system, it clips awkwardly on rounded buttons, and for years the only practical way to remove it was a single blanket rule at the top of a stylesheet:
/* Removes the focus indicator for every interactive element on the site */
*:focus {
outline: none;
}
That line ships on a large share of production CSS resets, frequently copied forward from a boilerplate or a previous project without anyone revisiting it. The problem: it doesn’t just remove the outline for a mouse click (where it’s arguably unnecessary) — it removes it for Tab, Shift+Tab, and every other form of keyboard navigation too. A sighted keyboard user tabbing through a checkout form with this rule in place has no way to see which field they’re about to type into. This is a different failure from a true keyboard trap — here focus moves correctly, the user just can’t see where it landed.
The fix: :focus-visible, not a blanket removal
The reason outline: none felt necessary in the first place — a focus ring appearing on every mouse
click, not just keyboard navigation — was a real design complaint, and browser vendors solved it
directly. The :focus-visible pseudo-class
“applies while an element matches the :focus pseudo-class and the user agent determines via
heuristics that the focus should be made evident on the element.” In practice, that heuristic means:
it matches on keyboard focus, and generally doesn’t match on a mouse click landing on a button.
That’s the mechanism that makes it safe to replace the default outline with a custom one, instead
of removing it:
/* Wrong: removes the indicator for keyboard users too */
button:focus {
outline: none;
}
/* Right: removes only the mouse-click ring; keyboard focus still gets a visible style */
button:focus {
outline: none;
}
button:focus-visible {
outline: 2px solid #1a56db;
outline-offset: 2px;
}
If a codebase needs to support older browsers without :focus-visible support, the safer fallback is
to simply leave the native outline alone and restyle it with outline-color/outline-width rather
than removing it — a visible-but-unstyled focus ring passes 2.4.7; a removed one doesn’t.
Contrast matters too — a faint indicator can still fail
Swapping in a custom focus style fixes the “no indicator at all” failure, but it can introduce a
quieter one: an indicator that’s technically present but too subtle to see. WCAG 1.4.11 Non-text
Contrast (Level AA) is explicit
about this: “in combination with 2.4.7 Focus Visible, the visual focus indicator for a component must
have sufficient contrast against the adjacent background when the component is focused” — a minimum
3:1 contrast ratio. A one-pixel outline that shifts a button’s border from #e5e5e5 to #eeeeee is
present, but it won’t clear that ratio against most backgrounds. A 2px solid outline in a color with
verified 3:1 contrast against the surrounding page background is the safer default for anything
custom-built.
New in WCAG 2.2: don’t let a sticky header hide the focused element
E-commerce sites lean heavily on sticky headers, sticky “Add to cart” bars, and cookie banners that
stay pinned to the viewport while the page scrolls underneath them. That creates a failure mode 2.4.7
alone doesn’t cover: the focus indicator can be technically visible and high-contrast, and still get
tabbed underneath a fixed element so the user can’t see it. WCAG 2.2 added SC 2.4.11 Focus Not
Obscured (Minimum)
(Level AA) specifically for this: “when a user interface component receives keyboard focus, the
component is not entirely hidden due to author-created content.” A common real-world case: a product
page with a sticky “Add to cart” footer bar tabs a shopper down through a long spec table, and the
last few fields scroll behind the fixed bar with no scroll-margin-top or scroll-padding-top
accounting for its height — the field has focus, but it’s invisible.
A simple CSS fix for that specific case:
/* Reserve space so a focused element doesn't scroll under a fixed header/footer */
:target,
:focus {
scroll-margin-top: 80px; /* match your sticky header's height */
}
WCAG 2.2 isn’t yet as widely cited as 2.1 in most accessibility content — it became a W3C Recommendation in October 2023 — but it’s the current version of the standard, and this specific failure mode is common enough on sites with sticky checkout bars or sticky filter headers that it’s worth checking for even on a 2.1 AA-scoped audit.
A two-minute manual test
Automated scanners can flag some of this — a missing :focus style entirely is detectable — but
“technically has an outline” and “visible enough to actually use” are different questions a scanner
can’t fully answer on its own. A quick manual pass:
- Click into the browser’s address bar, then press Tab once to land on the first focusable element on the page.
- Keep pressing Tab. At every stop, can you tell — without hunting — exactly which element is focused?
- Watch specifically for elements that disappear behind a sticky header, sticky footer, or open cookie banner as you tab past them.
- Compare a focused state against its background. If it’s a thin or low-contrast outline, check it against WebAIM’s Contrast Checker — you need 3:1 against the adjacent page background, not the 4.5:1 threshold used for text.
FAQ
Is it ever okay to use outline: none?
Only if a visible alternative replaces it for keyboard focus — for example, pairing
outline: none on :focus with a real style on :focus-visible, as shown above. Removing it with
nothing put back fails SC 2.4.7 regardless of intent.
Does a browser’s default focus ring automatically pass? Yes, for both 2.4.7 and 1.4.11. WCAG 1.4.11’s Understanding doc is explicit that “where the focus style of the user agent is not adjusted on interactive controls… by the website (author), the default focus style is exempt from contrast requirements (but must still be visible)” — the exemption isn’t conditional on background color, it applies as long as the site hasn’t touched the default style. It still doesn’t protect against the 2.4.11 sticky-header case, which is about position, not indicator style — a perfectly visible default ring can still end up scrolled behind a fixed header.
Do I need to redesign every focus state to match my brand? No — 2.4.7 only requires that focus be visible, not that it match a specific design. The default browser outline satisfies it. Custom styling is a design preference layered on top, and if it’s added, it inherits the 1.4.11 contrast requirement the default outline would have met automatically.
Get a human-reviewed audit, not just a scan
An automated scanner can tell you whether a :focus rule exists in your CSS. It can’t always tell
you whether the resulting indicator is visible enough on your actual background colors, or whether it
scrolls behind your sticky header on a real product page — that’s a judgment call a manual keyboard
pass catches and a rule-based scanner structurally can’t. Quietramp’s audits pair an automated
axe-core scan with a manual keyboard and screen-reader review of exactly this kind of issue,
delivered as a prioritized, developer-actionable PDF report. See a real sample
report or check pricing — $890 one-time, $99/month for ongoing
re-checks after fixes ship.
This is educational content about technical accessibility standards, not legal advice. Meeting WCAG 2.1 AA or WCAG 2.2 AA does not guarantee legal compliance with the ADA or any other law, and nothing here should be read as a compliance guarantee. Consult qualified counsel for legal risk questions.
This article was drafted with AI assistance and reviewed by a person for accuracy before publication.