Focus Management
Also Known As
focus trap
focus restoration
focus management
TL;DR
Programmatically controlling keyboard focus in SPAs and complex UIs — ensuring focus moves logically when modals open, routes change, and dynamic content loads.
Explanation
In static pages, browser focus follows natural tab order. In SPAs and dynamic UIs, focus management is the developer's responsibility. Key scenarios: modal opens (move focus to first interactive element), modal closes (return focus to trigger), route changes (move focus to main heading or skip-nav), inline errors appear (move focus to error summary), and notifications appear (announce via aria-live, not focus). Focus trapping in modals prevents tab from escaping into background content.
Diagram
flowchart TD
TRIGGER[User action opens modal] --> MODAL[Modal appears]
MODAL -->|move focus| FIRST[First focusable element in modal]
FIRST --> TRAP[Trap focus inside modal<br/>Tab cycles within]
TRAP --> CLOSE[User closes modal]
CLOSE -->|return focus| ORIGIN[Element that opened modal]
subgraph Focus_Indicators
VISIBLE[Visible focus ring<br/>never remove outline without replacement]
CONTRAST[High contrast indicator<br/>WCAG 3:1 minimum]
end
subgraph Common_Issues
SKIP[Focus jumps to background<br/>user lost in page]
LOST[Modal closes - focus goes to body<br/>not trigger element]
end
style FIRST fill:#238636,color:#fff
style ORIGIN fill:#238636,color:#fff
style SKIP fill:#f85149,color:#fff
style LOST fill:#f85149,color:#fff
Common Misconception
✗ Calling element.focus() is sufficient for SPA route changes — focus must move to meaningful content (h1 or main), not just any element; additionally, the page title should update for screen reader context.
Why It Matters
In a SPA without focus management, route changes leave keyboard users disoriented — focus remains on the navigation link while new content loads elsewhere on the page.
Common Mistakes
- Not trapping focus in modals — Tab key escapes the modal into background content, making the modal unusable for keyboard users.
- Removing focus from modals on close without returning it to the trigger — users lose their place in the page.
- Using tabindex='-1' on the target element but not calling .focus() — the element is focusable programmatically but .focus() must be called.
- Focusing a non-interactive container div — focus must land on an element with a meaningful accessible name.
Code Examples
✗ Vulnerable
// Modal without focus management:
function openModal() {
document.getElementById('modal').style.display = 'block';
// Focus stays on the button that opened the modal
// Keyboard users cannot navigate inside the modal
// Tab escapes to the page behind the modal
}
✓ Fixed
// Modal with proper focus management:
function openModal(trigger) {
const modal = document.getElementById('modal');
modal.style.display = 'block';
modal.setAttribute('aria-modal', 'true');
// Move focus to first focusable element:
modal.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])').focus();
// Trap focus inside modal:
modal.addEventListener('keydown', trapFocus);
}
function closeModal() {
document.getElementById('modal').style.display = 'none';
trigger.focus(); // Return focus to the element that opened the modal
}
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
29
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Perplexity 8
Amazonbot 7
Unknown AI 4
Google 3
Majestic 1
Ahrefs 1
SEMrush 1
Also referenced
How they use it
crawler 22
crawler_json 1
pre-tracking 2
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Medium
⚡ Quick Fix
After any dynamic content change (modal open, page route change, error message), programmatically move focus to the new content using .focus() on the container with tabindex='-1'
📦 Applies To
javascript ES5
web
🔍 Detection Hints
Modal dialog opens without moving focus inside it; AJAX content update without focus management; form error shown without focus moved to error
Auto-detectable:
✗ No
axe
nvda
jaws
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Medium
✗ Manual fix
Fix: Medium
Context: File
Tests: Update