← All criteria

Operable · Level A · 2.1.2

No Keyboard Trap

Once keyboard focus lands inside any part of a page — a widget, an embedded frame, a custom component — it always has to be possible to move focus back out using only the keyboard. If exiting needs something other than standard keys (Tab, Esc, arrow keys), the user has to be told how, in advance.

  • Blind
  • Motor
The problem, in practice — select the image to enlarge it
An online shop's 'Special offer' subscription modal, compared as a keyboard trap versus no keyboard trap. In the keyboard-trap example, pressing Tab or Shift+Tab cycles focus only among the modal's own controls (email field, Subscribe, Cancel, Privacy policy link) in an endless loop, so a keyboard user can never reach the rest of the page — Home, Products, About, Contact — again. In the no-keyboard-trap example, Tab still cycles through the modal's controls, but Shift+Tab from the first field moves focus back out to the page behind it, so focus can always exit using only standard keys (Tab, Shift+Tab, Esc).

How to recognize it

Tab into every interactive region of a page using only the keyboard and try to Tab or Esc back out of each one. A trap looks like this: focus lands inside an embedded widget, a date picker, or a custom component, and Tab just keeps cycling within it forever, with no visible way out and no announced alternative key combination. This is a total blocker for anyone who navigates by keyboard alone — blind screen reader users and people with motor disabilities who can't use a mouse — since once they're stuck, there's no way forward or backward through the rest of the page at all. A modal dialog that deliberately keeps focus contained while it's open is not a trap by itself, as long as a standard key (typically Esc) closes it and returns focus to where it came from.

How to fix it

Make sure every custom component, embedded frame, or third-party widget lets focus leave it using Tab, Shift+Tab, or Esc — the keys someone would try without being told anything special. If a component genuinely needs an unconventional way to exit, tell the user about it up front, before they get stuck, not after. Test any custom-built interactive component by tabbing all the way through the page with the mouse unplugged, literally or figuratively, and confirming you never get stuck anywhere.

Example

Avoid

<!-- custom widget captures Tab internally with no escape route and no instructions -->
<div id="custom-picker" tabindex="0" onkeydown="trapFocusForever(event)"></div>

Prefer

<!-- modal dialog: Tab cycles inside while open, Esc closes it and returns focus to the trigger -->
<div role="dialog" aria-modal="true" onkeydown="if (event.key === 'Escape') closeDialog()"></div>

Resources