Focus inside an overlay must stay within its interactive range
Aliases: focus containment · inert · focus cycle · modal focus
What it is
After a modal dialog, drawer, or full-screen menu covers the screen, keyboard focus still follows the document's global Tab chain — a stacking context does not stop at the overlay's edge. A focus trap (focus containment) cuts that chain at the overlay's interactive range and joins it into a loop: Tab and Shift+Tab cycle only among the overlay's controls; the page behind is neither focusable nor clickable. What is contained is "the nodes that are operable now", not every box in the overlay DOM.
This is where focus may travel while the overlay is open — not whether focus should move in on open, and not whether it should be restored on close.
Why it happens
Sequential focus navigation walks an open chain of focusable nodes in document order. An overlay is a higher paint layer; it does not rewrite that chain, so the stop after the last overlay button is often a link on the page behind. The user cannot see behind, yet can send focus there; input lands on a covered control, and a screen reader starts reading "the page below".
Both directions must be cut. Without a wrap at the first control, Shift+Tab still leaks. Marking the behind-subtree inert (or equivalently taking it out of focus and pointer hit-testing) keeps Tab, clicks, and accessibility-tree exploration off the covered page. Decorative scrims and unfocusable copy do not belong in the loop; omitting any clickable control (including Close) from the loop leaves a keyboard user unable to finish the overlay's task. pointer-events: none blocks pointers, not Tab.
Where it stops holding
Non-modal popovers, hover menus, and in-page filter trays should not trap focus — the user still needs to alternate with surrounding content; locking focus binds the context. Nested overlays trap only the top layer; the lower trap must yield, or two loops fight. A non-modal pop-up that accidentally gets inert on the main page disables the page it should leave usable. Touch-first sessions without a keyboard still need the trap: a hardware keyboard or assistive switch can appear at any time. A tell-only layer with no focusable controls must put Close or Confirm in the loop as the sole node; focus must not fall to body.
Applying it
- While a modal is open, cycle Tab among every interactive control inside it (including Close), and set
inert— or equivalent unfocusable, unclickable — on the behind root. - Do not rely on a dim scrim or
pointer-eventsalone. Do not force unfocusable decoration into the cycle. - For nested dialogs, keep only the top trap alive; pause the one underneath.
- How to check: with the overlay open, Tab and Shift+Tab at least two full loops; focus must not appear outside. Clicks on the page behind must do nothing. With a screen reader, exploration should stop at the overlay, not reach a covered heading.