2.4.7 Focus Visible
WCAG 2.2 · 2.4.7 AA Operable
This criterion belongs to Principle 2, Operable, under Guideline 2.4 Navigable. It is a long-standing Level AA requirement carried forward unchanged into WCAG 2.2.
What it requires
Any user interface that can be operated by keyboard must have a visible indication of which element currently has keyboard focus. As the user tabs through links, buttons, fields, and other controls, the element with focus must show a distinguishable focus indicator (such as an outline or ring) so its location is always apparent. The criterion does not mandate a specific style or contrast — only that a visible focus indicator exists. (WCAG 2.2 adds 2.4.13 Focus Appearance to govern the indicator's size and contrast; 2.4.7 governs only its presence.)
- Keyboard-only users — people with motor disabilities or who use switch devices and cannot use a mouse; without a visible indicator they cannot tell where they are on the page.
- Sighted users with low vision or cognitive disabilities who rely on a clear focus position to track and orient themselves.
- Power users navigating by keyboard for speed, who lose their place when focus is invisible.
How to detect it
| Method | What to do | Failure signal |
|---|---|---|
| Keyboard tab-through | Press Tab / Shift+Tab through every interactive control. | Focus moves but no visible indicator appears on one or more controls. |
| CSS inspection | Look for outline: 0 / outline: none with no replacement. |
Focus styling removed without a visible substitute. |
| Custom controls | Tab to scripted widgets (menus, tabs, custom buttons). | The roving-focus item shows no visible focus state. |
| Zoom / high contrast | Re-check at 200% zoom and in a high-contrast theme. | Indicator disappears against the changed background. |
| Automated tools | Run axe / Lighthouse. | Limited help — tools flag outline:none heuristically but cannot confirm a visible indicator; manual keyboard testing is required. |
How to fix it
- Never remove the default focus indicator without providing a clearly visible replacement.
- Prefer
:focus-visibleso the indicator shows for keyboard users without appearing on mouse clicks. - Use a high-contrast outline (with
outline-offset) rather than relying on colour change alone. - Give custom and scripted widgets the same visible focus treatment as native controls.
- Verify the indicator survives every theme, zoom level, and background it can appear on.
:focus-visible {
outline: 3px solid #1a73e8;
outline-offset: 2px;
}
Copy-paste tests
Automated coverage
There is no fully automated axe-core rule that confirms Focus Visible:
tools can flag outline:none heuristically but cannot verify that a visible
focus indicator actually appears. This criterion needs manual review —
use the console check and the keyboard steps below.
Run this in the browser console
// READ-ONLY: lists focusable controls that suppress their focus outline.
const focusable = document.querySelectorAll(
'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const suspects = [...focusable].filter(el => {
const s = getComputedStyle(el);
const noOutline = s.outlineStyle === 'none' || parseFloat(s.outlineWidth) === 0;
const noRing = s.boxShadow === 'none';
return noOutline && noRing;
});
console.log('Focusable controls:', focusable.length, '| suspects:', suspects.length);
console.table(suspects.map(el => ({
tag: el.tagName.toLowerCase(),
text: (el.textContent || '').trim().slice(0, 40),
outline: getComputedStyle(el).outline
})));
suspects.forEach(el => { el.style.outline = '2px dashed magenta'; }); // visual only, not saved
What to check manually: Tab through every control and confirm a
visible indicator appears on each — including custom/scripted widgets — and that
it stays visible at 200% zoom and in a high-contrast theme. The script cannot confirm a
:focus-visible or box-shadow ring is actually perceivable.