What 2.1.2 requires
If focus can be moved to a component using the keyboard, it must be possible to move focus away from it using only the keyboard. If leaving needs more than the usual keys (Tab, Shift+Tab, arrow keys or another standard exit such as Esc), the user must be told how. This is a plain-language summary. The normative text, including every exception, is in the W3C Recommendation, with the W3C's explanation in Understanding 2.1.2 (opens in a new tab) [1][2].
Exceptions and scope:
- Intentional containment is allowed. W3C's Understanding document notes that restricting focus to a modal dialog or popover doesn't fail, as long as the user knows how to leave it (for example with Esc or a Close button).
- Non-interference: this is one of the criteria that applies to all content on the page, even content that isn't relied on to meet other criteria, because a trap anywhere can block the whole page.
Why it matters
For someone who can't use a mouse, a keyboard trap is the end of the visit. Focus enters an embedded map, a chat widget, a video player or a date picker, and Tab just cycles inside it. There's no way to reach the rest of the page, so the only escape is to reload, and on a checkout that means starting over.
Common failures
Third-party embed that swallows Tab
A widget in an iframe handles every keystroke and never returns focus.
<!-- Fails -->
<iframe src="https://widget.example/chat"></iframe>
<!-- Better -->
<!-- Choose widgets that let Tab leave; test each vendor before shipping -->
<iframe src="https://widget.example/chat" title="Support chat"></iframe>Custom component that cancels every Tab
A script prevents the default Tab behaviour and never lets focus leave the component.
/* Fails */
editor.addEventListener('keydown', e => {
if (e.key === 'Tab') e.preventDefault();
});
/* Better */
editor.addEventListener('keydown', e => {
if (e.key === 'Tab' && !e.shiftKey && insideIndentMode) e.preventDefault();
// and document how to exit, e.g. 'Press Esc, then Tab'
});Modal with no keyboard way out
Focus is held in the dialog, but Esc does nothing and the close button isn't focusable.
<!-- Fails -->
<div class="modal"><span class="x" onclick="close()">×</span>…</div>
<!-- Better -->
<dialog aria-labelledby="t"><h2 id="t">…</h2>…<button type="button">Close</button></dialog>
<!-- showModal() gives Esc-to-close by default -->Focus loop after a dialog closes
The dialog is hidden but focus stays inside it, cycling through invisible controls.
/* Fails */
modal.hidden = true; // focus left inside
/* Better */
modal.close();
openerButton.focus();Can automated testing check 2.1.2?
No. axe-core maps no rules to 2.1.2. A trap only exists when someone presses keys and focus fails to leave. That's behaviour, not markup.
| axe-core 4.13.0 rule | What it checks |
|---|---|
| (none mapped) | axe-core 4.13.0 maps no rules to this criterion |
What automation can't decide: Whether focus can actually leave each component, whether a non-standard exit is explained, and whether a trap appears only in a certain state (a widget that has loaded, a modal opened from a specific button).
A clean automated result is never proof that 2.1.2 is met. See why sites pass axe-core but fail real screen reader users.
How to test it by hand
- Unplug or ignore the mouse. Start at the top of the page and press Tab until you have been through every interactive element and back to the browser chrome.
- Every time focus enters a component (embeds, editors, media players, maps, date pickers, chat widgets), try to leave with Tab, Shift+Tab and Esc.
- Open each dialog, menu and popover. Check you can close it with the keyboard and that focus returns to the control that opened it.
- If a component needs a special key to exit, check the instructions are visible or announced before focus enters it.
- Repeat on the key task pages (sign-in, checkout), where third-party widgets most often appear.
New to screen readers? Start with how to test a website with a screen reader and how to test keyboard-only navigation.
How Accessible helps (and where it stops)
This is where behavioural testing earns its keep. Real-user monitoring runs an observer for focus traps a keyboard user can't leave, along with dead-end Tab presses, in real sessions, and ranks each one by how many sessions met it (real-user monitoring). That includes traps in third-party widgets that only load for some visitors. Journeys operate the task keyboard-only, so a trap on the path through the task is reported at the step where it stopped. The assistant tools' keyboard walkthrough reports whether focus gets stuck in a loop on one page.
Where it stops: Accessible finds traps on the paths journeys take and in the sessions monitoring samples. A component nobody opened in those runs can still trap focus, so a manual keyboard pass over the whole page is still needed. No automated tool, ours included, can certify that a criterion is met.
Related criteria
Sources
- Understanding Success Criterion 2.1.2: No Keyboard Trap (opens in a new tab). W3C Web Accessibility Initiative. Accessed October 18, 2026.
- Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.1.2 (opens in a new tab). W3C Recommendation. Accessed October 18, 2026.
- axe-core rule descriptions (opens in a new tab). Deque Systems, axe-core 4.13.0. Accessed October 18, 2026.
- WAI-ARIA Authoring Practices Guide: Dialog (Modal) pattern (opens in a new tab). W3C. Accessed October 18, 2026.
Meeting a success criterion is not the same as legal compliance, which depends on the rules that apply to you. No automated tool can certify conformance.