Focus Management
Date: 2026-08-17
Deliberately controlling where keyboard focus sits after something changes. Static pages need none; anything that opens, closes or updates in place needs it — and getting it wrong strands people somewhere they can’t see.
Focus is the element currently receiving keyboard input. Focus management is moving it deliberately when the interface changes, rather than leaving it wherever it happened to be.
The principle: focus should end up where the person’s attention is. If the interface moved their attention, move focus to match.
The three situations that need it
1 SOMETHING OPENS
modal, drawer, expanded panel
→ move focus INTO it
2 SOMETHING CLOSES
→ RETURN focus to what opened it
3 CONTENT CHANGES IN PLACE
results update, an error appears,
a step advances
→ move focus to the change, or
announce it
Situation 2 is the most-missed. A modal that closes and drops focus back to the top of the document forces the person to tab all the way back to where they were — Keyboard Navigation.
Modals, in full
The canonical case, and it has five requirements:
1 move focus into the dialogue on open
→ the first focusable element, or
the heading with tabindex="-1"
2 TRAP focus inside while open
→ Tab from the last element wraps
to the first
3 Escape closes it
4 RETURN focus to the trigger on close
5 hide the background from assistive
technology
→ inert, or aria-hidden on the rest
Requirement 2 is the one people find counterintuitive — trapping focus is normally a failure, and inside an open modal it’s correct, because the content behind is not available.
<dialog> with showModal() provides 1, 2, 3 and 5 natively. Use it rather than rebuilding — Semantic HTML.
Where to send focus on open
THE DIALOGUE'S HEADING
with tabindex="-1"
→ the title is read first, giving
context
← usually the best choice
THE FIRST INTERACTIVE ELEMENT
→ efficient, and skips the context
THE PRIMARY ACTION
→ only where the dialogue is a
single confirmation
Never focus a destructive action, which invites an accidental Enter.
Content updating in place
FILTERS APPLIED
→ announce the new count via a live
region; do NOT steal focus
(they're still in the filter panel)
FORM SUBMITTED WITH ERRORS
→ move focus to an error summary at
the top, or to the first invalid
field
— Accessible Forms
STEP ADVANCED
→ move focus to the new step's
heading
INFINITE SCROLL LOADED
→ do NOT move focus. Announce
politely
See: Accessible Forms
The rule: move focus when the person’s task moved; announce when it didn’t. Stealing focus while someone is mid-task is worse than saying nothing.
Making a non-interactive element focusable
<h2 tabindex="-1" id="results-heading">
23 results
</h2>tabindex="-1" makes it programmatically focusable without adding it to the Tab sequence — the correct mechanism for headings and containers you want to move focus to.
Focus visibility
Covered in Keyboard Navigation. The essential: :focus-visible, never outline: none without a replacement, and the indicator must be visible against every background it can appear on — including inside modals and on coloured buttons.
Where it goes wrong
- Focus lost to
<body>after a dynamic update — the person is nowhere, and Tab starts from the top - Focus not returned after a modal closes
- Focus stolen on page load or by an autoplaying widget
- Focus on hidden elements. A closed-but-not-removed menu whose links are still focusable produces invisible tab stops
- Third-party widgets trapping focus, which is a full keyboard trap — Third-Party Scripts
Testing it
1 Tab to a control that opens something
2 activate it — where did focus go?
3 Tab around — can you leave? Should
you be able to?
4 Escape — did focus return to the
trigger?
5 submit a form with errors — where
is focus?
6 apply a filter — did focus move
unexpectedly?
Watching the focus ring while operating the site is the whole test, and it needs no tooling — which is why “hidden focus indicator” and “focus management missing” tend to be found together.