Hidden elements must not remain in the focus sequence
Aliases: focusable while hidden · off-screen focus · aria-hidden
What it is
Controls that are already visually gone—a collapsed section, a closed tab, an off-screen menu, a button hidden by means other than display—must not remain in the Tab sequence. Focus then jumps into blank space or across a long “nothing happened” gap and suddenly appears elsewhere. Hidden is a visual fact; the focus sequence must become the same fact.
Why it happens
CSS visibility and focusability are not the same switch. opacity: 0, visibility: hidden, off-screen translation, and zero-height collapse often leave an element focusable; display: none and the hidden attribute usually take it out. aria-hidden tells assistive technology not to read the subtree but does not by itself forbid focus, so a screen reader skips it while a keyboard user can still stop there. Unmounted-looking routes that are still in the tree, pre-rendered drawers, and carousel slides not in the current frame leave a set of unseen controls that still receive Space and Enter. Failures come in two shapes: focus “swallowing” several Tabs in blank space, and a hidden button firing by accident. Both come from painting and focusability being separate knobs.
Studying it
For every show/hide component, Tab the whole page in the hidden state. Record whether focus enters an invisible node and whether a hidden control can be activated with Space. Independent variables include hiding technique (display, visibility, off-screen, aria-hidden) and component type; dependent measures include count of focusable nodes while hidden, blank hops, and accidental activations. A screenshot that looks empty in the hidden state misses the sequence problem. Walk without a pointer, with a focus outline on, so landings can be seen.
Where it stops holding
An off-screen “skip to main content” link placed deliberately at the start of the sequence is not an accidental leftover. Visually hidden text meant for screen readers should not take focus unless it is itself a control. A transient in the middle of an animation (a drawer sliding out) may be briefly both visible and focusable; cut the sequence at the end of the animation, not the start, so focus is not yanked mid-motion.
Applying it
- When hiding a focusable control, use a method that removes it from the sequence, or also set
inert/tabindex="-1"; do not rely on opacity and off-screen placement alone. - A subtree with
aria-hidden="true"must contain no focusable nodes; the two switches close together. - Keyboard-walk the page in the closed state of every collapse, tab set, and drawer; count hops into invisible regions. The target is zero.