accessibility · keyboard
Focus trap
also called focus containment, focus sentinel, focus lock (community)
A constraint that keeps keyboard focus cycling inside one region until that region is dismissed.
A modal dialog is modal because focus cannot get out of it. That is the whole mechanic: Tab from the last control inside the region goes to the first control inside the region rather than to whatever sits behind, and Shift Tab from the first goes to the last. Without it the surface only looks modal. A scrim dims the page and blocks the pointer, and a keyboard user tabs straight through it into a form they cannot see.
It is the same code as a keyboard trap, and the difference is not subtle, it is the exit. A focus trap publishes one: Escape closes the region, a visible close control does the same, and both hand focus back to whatever opened it, so the reader returns to the sentence they were in the middle of. A keyboard trap is this cycle with nothing that ends it, and WCAG 2.1.2 fails it. The pair with initial focus is the other half of the contract: something has to decide where focus lands when the region appears, and something has to give it back when the region goes. A trap that holds focus and then drops it at the top of the document has only done half the job.
Modern implementations do not police the foreground at all. Inert seals the
background instead: put it on everything outside the region and the browser takes those
subtrees out of focus order, out of hit testing, and out of the accessibility tree
together, so there is no wrapping to write and no sentinel node to maintain. A <dialog>
opened with showModal() gets that for free, since the browser makes everything outside
the top layer inert on its own. The older pattern, still what most libraries ship, is a
pair of invisible focusable sentinels either side of the region that bounce focus back
when it reaches them, which is where the alias “focus sentinel” comes from.
Three things go wrong often enough to check for by hand. A trap built from a static list
of controls collected on open goes stale the moment the region’s content changes, so
recompute the tabbable set or use inert and stop maintaining a list. A trap that
survives its own region, usually because the listener was never removed on close, is a
keyboard trap with a good origin story. And the trap belongs to modality, not to
convenience: holding focus inside a non-modal popover, a cookie banner, or an inline
editor takes the page away from someone who never asked to be somewhere else. If the
reader is allowed to leave the surface open and go do something else, do not trap them
in it. Focus management is the wider practice this one decision
sits inside.
Which word?
| If you want | say |
|---|---|
| focus deliberately held inside one region | focus trap |
| making a whole region unreachable, not just invisible | inert |
| focus goes in and cannot be tabbed back out | keyboard trap |
| deciding where focus goes when the UI changes | focus management |
| darkening what is behind so the layer above stays readable | scrim |
Related
See also: Modal dialog · Initial focus
Implementations
Specimens illustrate the concept; for production use, start here.
| aria-apg | Dialog (Modal) Pattern |