The keyboard:trap rule flags an element that keyboard focus can enter but not leave: Tab, Shift+Tab and Escape all leave focus where it is. For somebody without a mouse, the page ends there. The fix is to let the standard keys move on – or, where a widget really needs Tab, to offer a way out and say what it is.
What the rule means
WCAG 2.1.2 requires that when focus can be moved into a component with the keyboard, it can also be moved out with the keyboard alone. If leaving takes anything other than the standard keys (Tab, Shift+Tab, arrow keys, Escape), the person has to be told how.
A trap is not the same as a modal dialog keeping focus inside itself. A dialog that holds focus until it is closed – with Escape or a close button – is doing the right thing, because the rest of the page is not usable while it is open.
Who is affected
Everyone who uses a keyboard instead of a mouse: people with motor disabilities using a keyboard, switch or mouth stick, blind people using a screen reader, and power users. A trap is the most severe keyboard failure there is. Nothing on the rest of the page can be reached, often not even the browser's address bar without shortcuts many people do not know.
Why the check fails
- Text editors and code fields that insert a tab character when Tab is pressed, with no other way to move on.
- Embedded players and maps (iframes, canvas, plugins) that take focus and never hand it back.
- Focus loops in menus, carousels or chat widgets that were built like a modal dialog but are not one.
- Scripts that return focus to a field on
blur, for example to force a valid entry before moving on. - Date pickers and custom selects that capture every key while open and have no Escape handling.
How to fix it
Let Tab and Shift+Tab do what they always do. Where a widget needs a key for itself, give it a different one and say so.
<!-- Before: the note field swallows Tab and Escape -->
<label for="note">Note</label>
<textarea id="note"
onkeydown="if (event.key === 'Tab' || event.key === 'Escape') {
event.preventDefault(); /* inserts nothing, and keeps focus */
}"></textarea>
<button type="button">Save</button>
<!-- After: Tab moves on; indenting has its own shortcut, and says so -->
<label for="note">Note</label>
<textarea id="note" aria-describedby="note-hint"
onkeydown="if (event.ctrlKey && event.key === ']') {
event.preventDefault();
this.setRangeText('\t', this.selectionStart, this.selectionEnd, 'end');
}"></textarea>
<p id="note-hint">Ctrl + ] indents the current line.</p>
<button type="button">Save</button>
For custom widgets:
- Escape closes anything that opened (menus, pickers, pop-ups) and returns focus to the control that opened it.
- A real modal uses
<dialog>withshowModal()orrole="dialog"witharia-modal="true", and always has a way to close it. - Embedded content: check third-party players and maps with the keyboard before you ship them; if one traps focus, it is your page that fails.
How to test it manually
- Click into the address bar and press Tab until you have visited every control on the page.
- At every widget, try to leave it: Tab, Shift+Tab, then Escape.
- Open every menu, date picker and dialog, and close it again with the keyboard alone.
- Check embedded content (videos, maps, chat) the same way. A trap usually hides in something you did not build yourself.
Related WCAG criterion
2.1.2 No Keyboard Trap, Level A. Related: 2.1.1 Keyboard, because everything has to be operable by keyboard in the first place, and 2.4.3 Focus Order.
How Reviseberg reports it
This rule does not come from axe-core: a trap only shows up when somebody presses keys. Reviseberg's keyboard agent walks the journey you choose with real key presses in Chromium. When a Tab press leaves focus on the same element as before, it tries Shift+Tab and then Escape. Only if focus is still there after all three does it report the trap – "Focus cannot leave this element with Tab, Shift+Tab or Escape" – and stop the walk, because nothing after that point is reachable. Focus held inside an open modal dialog (<dialog open> or role="dialog" with aria-modal="true") is not reported.
The finding carries the selector, the step in the keystroke trail and, on a full crawl, a cropped screenshot. The agent does not press Escape and then Tab: a widget that is left that way – some code editors are – is reported as a trap. If your page tells people how to leave, mark the finding as a false positive with that reason.