In 25 years of using JAWS as my primary screen reader, I have encountered every variety of focus indicator failure. The completely invisible focus ring. The 1px dotted outline that disappears against a white background. The browser default outline removed without replacement. The custom focus style that only works in Chrome and nowhere else.
WCAG 2.2, finalized as a W3C Recommendation in October 2023, introduced Success Criteria 2.4.11 and 2.4.12, which for the first time in WCAG history establish measurable, concrete requirements for focus indicator appearance at Level AA and Level AAA respectively. Developers I audit regularly get both of these wrong — not because they do not care, but because the language of the success criteria is genuinely complex to parse.
Let me break down exactly what is required, show you what compliant and non-compliant focus styles look like, and give you the CSS patterns that will pass an audit.
Why Focus Styles Matter More Than You Might Think
Focus indicators are not just for screen reader users. They matter for:
- Keyboard-only users who navigate entirely without a mouse — including people with motor disabilities, power users, and anyone whose mouse has failed
- Users with low vision who can see the screen but need high-contrast visual cues to track where they are
- Cognitive disability users who rely on visible context to understand what is currently selected
- Screen reader users who sometimes switch between screen reader navigation and keyboard navigation
When I navigate with JAWS, I hear the focus move. But when I do testing sessions with users who have low vision and use a keyboard without a screen reader, the focus indicator is their only signal of where they are on the page. Removing it or making it inadequate is the equivalent of making the mouse cursor invisible for mouse users.
SC 2.4.11 Focus Appearance (Minimum) — Level AA
This is the criterion that matters for WCAG 2.2 AA conformance. The requirement has two parts:
Part 1: The Perimeter Requirement
The focus indicator has an area equal to or greater than the perimeter of the unfocused component, calculated using the formula: CSS offset height × 2 + CSS offset width × 2.
In plain language: the focus indicator must at minimum outline the entire component. An underline-only focus style on a button fails this requirement. A partial border fails. The indicator must form a complete perimeter around the component.
Part 2: The Contrast Requirement
The focus indicator area has a contrast ratio of at least 3:1 between the focused and unfocused state of the component.
This means the indicator must be visually distinguishable from both the background and from the unfocused state of the component. A blue outline on a blue button fails — there is not enough contrast between the focused state and the unfocused state.
SC 2.4.12 Focus Appearance (Enhanced) — Level AAA
The enhanced version requires:
- The focus indicator encloses the entire UI component
- The focus indicator is at least 2 CSS pixels thick
- The contrast ratio is at least 3:1 between focused and unfocused states
- The focus indicator is not entirely hidden by the author's styling
If your organization targets AAA conformance — common in government and enterprise contexts — 2.4.12 is your benchmark. For most projects, 2.4.11 is the requirement to meet.
The Most Common Focus Style Failures I Find in Audits
Failure 1: outline: none With No Replacement
This is the most common accessibility failure I encounter across all sites I audit. A designer removes the default browser focus outline because it "looks ugly" and no replacement is implemented. The result is invisible focus for all keyboard users.
/* The most dangerous line in CSS */
:focus { outline: none; }
/* Slightly better but still dangerous */
:focus { outline: 0; }
/* Best practice: suppress only for mouse users, preserve for keyboard */
:focus:not(:focus-visible) { outline: none; }
:focus-visible { outline: 3px solid #66FCF1; outline-offset: 3px; }
The :focus-visible pseudo-class is your friend here. It only applies when the browser determines the user is navigating with a keyboard, hiding the focus ring for mouse users (who typically find it distracting) while keeping it fully visible for keyboard users. Browser support is excellent — all modern browsers support it, and it can be safely polyfilled for older browsers.
Failure 2: Low-Contrast Focus Indicators
A light gray outline on a white background. A blue outline on a dark blue button. A thin dotted border that barely registers. These fail the 3:1 contrast requirement between focused and unfocused states.
/* Failing: low contrast outline */
:focus-visible {
outline: 1px dotted #999; /* May not meet 3:1 on white background */
}
/* Passing: high contrast, sufficient size */
:focus-visible {
outline: 3px solid #66FCF1; /* High contrast cyan on dark */
outline-offset: 2px;
}
/* For light theme: */
[data-theme="light"] :focus-visible {
outline: 3px solid #007a76; /* Dark teal, high contrast on white */
outline-offset: 2px;
}
Failure 3: Indicators That Are Too Thin
A 1px outline does not reliably meet the "area equal to or greater than the perimeter" requirement in all cases. For the perimeter of the indicator to equal the perimeter of the component, the indicator needs to be a complete ring with sufficient width to register visually against any background it might appear on. I recommend a minimum of 2px for AA compliance and 3px for practical visibility.
Failure 4: Focus Styles Hidden by overflow: hidden
This one is subtle and appears frequently in cards and containers. A parent element has overflow: hidden set (often to contain rounded corners or prevent scrollbars). When a child element receives focus, the outline-offset or the outline itself renders outside the parent's bounds and gets clipped.
/* The problem: */
.card {
border-radius: 12px;
overflow: hidden; /* Clips child outlines */
}
/* Solution 1: Use box-shadow instead of outline */
:focus-visible {
outline: none;
box-shadow: 0 0 0 3px #66FCF1, 0 0 0 5px #0B0C10;
}
/* Solution 2: Use outline with negative offset */
:focus-visible {
outline: 3px solid #66FCF1;
outline-offset: -3px; /* Brings outline inside the element */
}
/* Solution 3: Remove overflow hidden if it's not necessary */
.card {
border-radius: 12px;
/* overflow: hidden; — removed, use clip-path instead */
clip-path: inset(0 round 12px);
}
A Complete Focus Style System for WCAG 2.2 AA Compliance
Here is a complete CSS system you can drop into any project. It covers the standard cases, handles light and dark themes, and works within overflow-constrained containers:
/* ============================================
FOCUS STYLE SYSTEM — WCAG 2.2 AA Compliant
============================================ */
/* Base: Remove default only for non-keyboard navigation */
:focus:not(:focus-visible) {
outline: none;
}
/* Standard focus visible — works on most elements */
:focus-visible {
outline: 3px solid #66FCF1;
outline-offset: 3px;
border-radius: 3px;
}
/* High-contrast override for light backgrounds */
@media (prefers-color-scheme: light) {
:focus-visible {
outline-color: #007a76;
}
}
/* Windows High Contrast Mode support */
@media (forced-colors: active) {
:focus-visible {
outline: 3px solid ButtonText;
}
}
/* For elements inside overflow:hidden containers */
.card :focus-visible,
.overflow-container :focus-visible {
outline: none;
box-shadow:
0 0 0 3px #66FCF1, /* The indicator */
0 0 0 6px #0B0C10; /* Gap between indicator and element */
}
/* For dark backgrounds where outline might need contrast boost */
.dark-section :focus-visible {
outline: 3px solid #F2A900; /* Yellow for maximum contrast on dark */
}
How to Audit Your Own Focus Styles
Before you run any automated tool, do this manual test:
- Open your site in Chrome, Firefox, and Safari.
- Press Tab to begin keyboard navigation.
- Tab through every interactive element — links, buttons, form fields, dropdowns, custom widgets.
- At each element, ask: Can I see where I am? Is the indicator clearly visible against the background? Does it surround the entire element?
- Trigger any modal dialogs, dropdowns, or dynamic content and Tab through those too.
- Zoom the page to 200% and repeat — focus indicators sometimes become harder to see at different zoom levels.
Then run the WCAG Color Contrast Analyzer tool on any focus indicators you are uncertain about. Measure the contrast between the indicator color and both the background color and the unfocused component color. You need at least 3:1.
The Bottom Line on Focus Styles
Twenty-five years of navigating the web with a screen reader, and I can tell you: poor focus styles are the single most consistent barrier I see for keyboard users who do not use screen readers. They hit every person who ever navigates a form with Tab, every power user who prefers keyboard shortcuts, and every person with a motor disability who cannot reliably operate a mouse.
WCAG 2.2 finally gave us a testable, measurable requirement for focus appearance at Level AA. There is no longer a defensible reason for invisible or inadequate focus indicators. The browser default is getting better, but it is still not reliable across all browsers and themes. Own your focus styles. Test them. Make them visible.
Need a real accessibility audit?
Not a Lighthouse score — a thorough WCAG 2.2 AA audit with manual JAWS testing and code-level remediation guidance your developers can actually use.
Schedule a Free Consultation