2.1.2 No Keyboard Trap
- Level A
- Operable
- Since WCAG 2.0
Summary
A keyboard trap is a dead end: focus moves into a component and no keystroke will move it out again. For someone who cannot use a mouse (people with motor disabilities, screen reader users, switch users driving a keyboard interface), a single trap does not degrade the page, it ends the session. The only way out is to reload and lose whatever they were doing. That is why WCAG lists this criterion among its non-interference requirements: a trap anywhere on the page fails the page, even inside content you would otherwise scope out.
The auditor's mental model has two halves. First, everywhere focus can go, focus must be able to leave using the keyboard alone. Second, leaving does not have to be Tab: a non-standard exit is permitted, provided the user is told about it. And note the important distinction that intentional containment is not a trap. A modal dialog that deliberately keeps Tab cycling within it is correct behaviour, as long as Escape or a reachable close control releases focus. Grade the exit, not the containment.
Official wording
If keyboard focus can be moved to a component of the page using a keyboard interface, then focus can be moved away from that component using only a keyboard interface, and, if it requires more than unmodified arrow or tab keys or other standard exit methods, the user is advised of the method for moving focus away.
EN 301 549 mapping
- Web pages
- Clause 9.2.1.2
- Software and native apps
- Clause 11.2.1.2 (via Table 11.3)
Clause 9.2.1.2 applies this criterion to web pages unchanged. For software, clause 11.2.1.2 carries the requirement through a word-substitution table (Table 11.3) that restates it for application user interfaces.
Clause references are to EN 301 549 V3.2.1 (2021-03), the harmonised European standard. Descriptions are our own summary, not the text of the standard.
In practice
Web
Put the mouse aside and Tab forward through the entire page, then Shift+Tab back through it. The suspects are almost always embedded or third-party content: iframes, video and audio players, chat widgets, embedded maps, ad frames, canvas-based apps, and custom rich text editors. Enter each one deliberately, interact with it, then try to leave in both directions. If Tab and Shift+Tab stop working, try Escape, arrow keys, and any exit the component advertises before you record a fail; a documented non-standard exit passes.
Confirm the trap is real before grading it. In browser developer tools, log document.activeElement in the console while you press Tab: if focus is genuinely cycling within one component (or not moving at all), you have a trap; if focus is moving but you cannot see it, you have a focus visibility problem instead, which files under a different criterion. Distinguishing the two is the single most important verification step for this criterion.
Common web failure spots: embedded players whose internal controls loop forever, chat widgets that mount a focused overlay with no keyboard close, rich text editors that repurpose Tab for indentation without offering or advertising an escape, and broken modals that trap Tab but ignore Escape and put the close button outside the focus cycle. Also test what happens after a component removes itself: a widget that dismisses on Escape but leaves focus on a removed node can strand the keyboard just as effectively.
iOS
This criterion has a software equivalent: for applications, the European standard restates it for application user interfaces, so native app screens are graded, not just web pages. Test with a hardware Bluetooth keyboard, with Full Keyboard Access enabled (Settings, Accessibility, Keyboards, Full Keyboard Access), which makes the whole interface reachable by Tab and arrow keys.
Move focus through every screen and, in particular, into every layered surface: custom modal sheets, bottom sheets, popovers, and any WKWebView embedding web content. Inside each, confirm you can move focus back out with the keyboard alone; with Full Keyboard Access, Escape should dismiss modal layers, and Tab should eventually return to the presenting screen. The classic iOS traps are custom overlay views that intercept key input without handling dismissal, and web views whose embedded content captures focus so the keyboard can never return to the surrounding native chrome. Use Accessibility Inspector or the Xcode view debugger to confirm which element actually holds focus when navigation appears stuck.
Android
The software restatement applies equally here. Pair a hardware keyboard and drive the app with Tab, Shift+Tab, arrow keys, and Escape (which Android maps to Back for dismissing dialogs and sheets). Walk focus through every screen, then into every dialog, custom bottom sheet, and embedded WebView, and confirm focus comes back out.
The recurring Android failure spots: custom dialogs built from plain views that consume key events without a keyboard dismissal path, embedded WebView content that holds focus so Tab never re-enters the native layout, and full-screen custom layers (image viewers, story-style overlays, in-app browsers) that respond only to touch gestures. Where a screen offers a non-standard exit (for example, a game view that releases focus on a specific key), check that the app states the method visibly or through an accessible instruction; an undocumented magic keystroke does not pass. On device, "Show layout bounds" plus keyboard focus highlighting in developer options helps confirm where focus really is when it seems stuck.
Pass and fail examples
Passes:
- A modal dialog cycles Tab within itself while open, closes on Escape, and returns focus to the trigger: intentional containment with a standard exit.
- An embedded video player takes focus into its controls and releases it in both directions with Tab and Shift+Tab.
- A code editor uses Tab to indent, and text directly above it says "Press Escape, then Tab to move focus out of the editor": a non-standard exit, advertised.
- A chat widget's panel opens with focus inside it and its close button sits inside the Tab cycle, so the keyboard can always dismiss it.
Fails:
- A third-party booking iframe accepts Tab into its form, and Tab, Shift+Tab, and Escape all cycle inside it forever: the rest of the page is unreachable without a reload.
- A custom modal traps Tab within itself, ignores Escape, and renders its close icon as a non-focusable div: containment with no keyboard exit.
- A canvas-based configurator captures all key input on focus and only a mouse click outside releases it.
- An editor repurposes Tab for indentation and does offer Ctrl+M to toggle out, but nothing in the interface or its accessible instructions mentions it: the exit exists but the user is not advised.
- A native app's custom overlay swallows hardware keyboard input so neither Escape nor Tab ever leaves it.
Not a fail under this criterion:
- A control the keyboard cannot reach at all: focus never enters it, so no trap exists; the missing reachability files under SC 2.1.1 Keyboard.
- Focus that moves in a confusing or illogical sequence but always moves on: that is SC 2.4.3 Focus Order.
- Focus that leaves the component fine but is invisible while doing so: file it under SC 2.4.7 Focus Visible, and verify with the developer tools that focus genuinely moved.
- A modal that constrains Tab within itself while open: containment is the intended dialog behaviour and passes, provided Escape or an in-cycle close control works.
Commonly confused with
- SC 2.1.1 Keyboard. 2.1.1 asks whether functionality is operable by keyboard at all; 2.1.2 asks whether focus can leave once it arrives. "I cannot get in" is 2.1.1, "I cannot get out" is 2.1.2. They are graded independently: a widget can be fully operable and still trap focus at its far edge.
- SC 2.4.3 Focus Order. A bizarre focus sequence that jumps around the page is a focus order finding, not a trap, as long as repeated Tab presses eventually progress. Reserve 2.1.2 for focus that cycles or freezes.
- SC 2.4.7 Focus Visible. An invisible focus indicator produces the same symptom as a trap: the user presses Tab and nothing appears to happen. Confirm with
document.activeElement(or the platform inspector) before choosing the criterion; misfiling this one wastes remediation effort on the wrong fix. - Screen reader virtual cursor loops. A screen reader's browse mode getting stuck in a region is often a reading mode or markup problem rather than a keyboard focus trap. Test 2.1.2 with the screen reader off first; only genuine focus traps in the keyboard interface belong here.
How AUDITSU tests this
AUDITSU's audit walkthrough puts a keyboard trap check on every screen you review. The walkthrough prompts you to traverse the screen with Tab and Shift+Tab, to enter each embedded or layered component (iframes, players, chat widgets, modals, web views), and to confirm focus comes back out, trying standard exits before grading. Where a component uses a non-standard exit, the walkthrough asks whether the method is advertised to the user. Each check records a pass, fail, or not applicable result per screen with evidence attached, so a trap is tied to the exact screen and component that caused it.
Because the European standard carries this requirement through to application user interfaces, the same walkthrough questions run against native iOS and Android screens with a hardware keyboard connected, not just web pages.
For the full guided workflow, see the audit platform.