J3.02.5dynamic focus orderdesignresearch

Focus order must update as content expands or hides

Aliases: accordion focus · hidden still focusable · live tab set

What it is

The set of tab stops is not a roster photographed at page load. It is a live set of currently visible objects. When an accordion opens, the links and fields inside must join the sequence at once; when it closes, they must leave at once. The same rule covers tab panels, collapsed sections and a mobile menu that shuts. If order does not rewrite with visibility, people Tab into a region they cannot see, or never reach the content just expanded.

This is not the same as “after a new node is inserted, focus stays on the old button”. That is where the caret sits. This is who is still on the list.

Why it happens

From the keyboard, a node can be “absent” in three different ways. display: none / hidden usually removes it from the sequence. visibility: hidden or a zero-opacity layer can vanish visually while remaining a tab stop. aria-hidden edits the accessibility tree and does not, by itself, edit Tab. An off-screen menu parked at negative coordinates is gone for the pointer and still a long run of real controls for Tab.

The mirror failure on expand: content is painted but still carries tabindex="-1" or a parent inert that was never lifted, so a field that looks new cannot be reached. The product implemented “visible” as a style switch and left “reachable” in the previous state. Two switches out of sync freeze the live set on an expired roster.

Studying it

Walk each disclosure twice. Tab a full cycle while collapsed and log landings; expand and Tab a full cycle again; diff the sets. Stops that remain focusable while collapsed are “ghost stops”. Stops that should have joined on expand but did not are “roster not written”.

Mobile hamburger menus freeze the roster especially often: the icon is gone after close, the links remain in the sequence, focus walks off-viewport. Measure that state on its own.

Where it stops holding

Wizard steps that are pre-rendered but not yet current should not be focusable even if the fields already exist in the DOM. Carousel slides that are not the current frame should not be stops either. Conversely, content that is off-screen but still logically visible (items in a scrollport not yet scrolled into view) should stay in the sequence — that is overflow, not hiding. inert and aria-hidden can drift apart for a few frames during animation; by the time the animation ends the set must already have changed. Do not defer the rewrite to the next click.

Applying it

  • Hide by removing from the sequence: hidden, display: none, or inert. Do not rely on opacity or parking off-screen.
  • The moment expand finishes, lift inert / negative tabindex so the new fields are reachable.
  • How to check: open then close a nav drawer or accordion, Tab only. If focus walks into empty space after close, or newly revealed links take a long detour after open, the live set did not follow.

Related

  • Same group: J3.02.1 Focus order must match visual order · J3.02.2 Overlays must capture focus and remain escapable · J3.02.3 An inescapable focus trap is a blocking defect · J3.02.4 Dynamically inserted content desynchronizes focus unless it is moved on purpose · J3.02.6 Focus-order failures are found by walking with a keyboard, not by inspecting source order · J3.02.7 Nested overlays that each capture focus can deadlock
  • Nearby: J5.10 Name, role and value · J2.14 Headings and landmarks · E4.11 Modeless panels
  • Search terms: inert · hidden tab stop · disclosure focus

Cards in the same group

Quick Actions

Share

Share this page

ios_share

https://hci.top/en/handbook/J3.02.5