Definition: A keyboard trap is a component you can move into with the keyboard but cannot leave with the keyboard. WCAG success criterion 2.1.2 No Keyboard Trap forbids it at Level A [1].
German: Tastaturfalle · Also: focus trap · Last reviewed: 27 September 2026
Why it matters so much
People who don't use a mouse move through a page with Tab and Shift + Tab. That includes blind people using a screen reader, people with motor disabilities using a keyboard, a switch or a mouth stick, and many experienced users who are simply faster without a mouse. When focus gets stuck, the rest of the page is out of reach. Often the only way out is to close the tab.
WCAG treats 2.1.2 with particular strictness. It is one of four "non-interference" requirements: it must hold for all content on the page, including parts that are not meant to contribute to conformance, such as an embedded third-party widget [3].
Where keyboard traps appear
- Embedded players and iframes – third-party video players, maps, booking or chat widgets.
- Editors that capture Tab for indentation without offering a way out.
- Custom dialogs and menus whose focus logic only handles getting in.
- Date pickers, sliders and carousels that swallow key events with
preventDefault(). - Cookie banners that hold focus but cannot be closed from the keyboard.
Deliberate focus containment in dialogs is not a trap
A modal dialog may, and should, keep focus inside while it is open [4]. It only becomes a trap when you cannot leave: Escape does nothing and there is no reachable close button. If a component needs an unusual key to exit, it must say so – "Press Ctrl + M to leave the editor", for example [2].
In code
// Trap: Tab is always intercepted
editor.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
e.preventDefault()
insertIndent()
}
})
// Better: Escape releases Tab
let indent = true
editor.addEventListener('keydown', (e) => {
if (e.key === 'Escape') { indent = false; return }
if (e.key === 'Tab' && indent) {
e.preventDefault()
insertIndent()
}
})
editor.addEventListener('focus', () => { indent = true })
// Visible hint: "Tab indents.
// Press Escape, then Tab, to leave the editor."
How to test it
Click into the address bar and put the mouse away. Tab through the whole page, then Shift + Tab back. Open every dialog, menu and embedded element and leave it again with Tab, Shift + Tab and Escape. Can you get into everything and back out?
How Reviseberg handles it
Reviseberg's keyboard agent walks your most important user journey with real key presses: Tab, Shift + Tab, Enter, Space and Escape. When focus gets stuck, it reports the rule keyboard:trap with the keystroke trail step by step and a screenshot of the spot. It tests the journey you define, not every possible path on every page. A rules scan with axe-core alone cannot find keyboard traps, because it never presses a key.
Related terms
Keyboard accessibility · Focus order · Focus indicator · Skip link · Screen reader