No Login Data Private Local Save

Dialog Focus Manager Demo - Online A11y Trap & Restore

6
0
0
0

Dialog Focus Manager

A live demonstration of focus trapping & restoration — an essential accessibility (A11y) pattern for modals and dialogs. Open the dialog below and navigate with Tab Shift+Tab Esc to see the trap in action.

Click the button below to launch the demo dialog

Use Tab to navigate forward  Â·  Shift+Tab backward  Â·  Esc to close

Focus Trap Inspector
Status Inactive
Trigger Element —
Current Focus —
Focusable Elements 0
Tab Order Map
  • Dialog not open
Event Log
Waiting for dialog interaction...

Frequently Asked Questions

A focus trap is an accessibility pattern that confines keyboard focus within a specific container (such as a modal dialog) while it is active. When a user presses Tab or Shift+Tab, focus cycles only through the interactive elements inside the container — never escaping to the background page. This is critical for users who rely on keyboards or screen readers, as it prevents them from accidentally interacting with content behind an open modal. The WCAG 2.1 Success Criterion 2.4.3 (Focus Order) and 4.1.3 (Status Messages) relate directly to proper focus management.

Focus restoration ensures that when a modal or dialog is dismissed, keyboard focus returns to the element that originally triggered it. Before opening the dialog, the application stores a reference to document.activeElement (the trigger button). When the dialog closes — whether by Esc, clicking the backdrop, or activating a close button — focus is programmatically moved back to that saved element. This maintains the user's context and prevents disorientation. Without focus restoration, a keyboard user might be dumped at the top of the page, forcing them to tab all the way back.

  • Not trapping focus at all — focus escapes the modal into the background page.
  • Forgetting to restore focus — after closing, focus is lost or lands on <body>.
  • Ignoring Shift+Tab — only handling forward Tab navigation, leaving reverse navigation broken.
  • Not setting aria-modal="true" — screen readers may not announce the modal context correctly.
  • Focusing the wrong first element — the first focusable element should be logical (often the close button or first form field).
  • Not preventing body scroll — the background page remains scrollable behind the overlay.
  • Hardcoding selectors — using a fixed list instead of dynamically querying focusable elements.

A comprehensive focus trap should account for these selectors:
  • a[href] — anchor tags with an href attribute
  • button:not([disabled]) — enabled buttons
  • input:not([disabled]):not([type="hidden"]) — visible, enabled inputs
  • select:not([disabled]) — enabled select dropdowns
  • textarea:not([disabled]) — enabled textareas
  • [tabindex]:not([tabindex="-1"]) — elements with explicit non-negative tabindex
  • [contenteditable="true"] — editable content regions
  • details > summary — interactive summary elements
  • audio[controls], video[controls] — media controls
Additionally, only visible elements (with actual rendered dimensions) should be included in the tab cycle.

Manual testing steps:
  1. Open a modal/dialog using the keyboard (Enter or Space on the trigger).
  2. Press Tab repeatedly — focus must stay inside the dialog, looping from last to first element.
  3. Press Shift+Tab — focus must cycle backward, looping from first to last element.
  4. Press Esc — the dialog should close and focus must return to the trigger element.
  5. Click the backdrop overlay — same close + restore behavior.
  6. Verify that background content is not reachable via Tab while the dialog is open.
  7. Use browser DevTools to run document.activeElement in the console to confirm focus location.
  8. Test with a screen reader (NVDA, VoiceOver, JAWS) to verify announcements.

Yes! The native HTML <dialog> element (supported in all modern browsers) provides built-in focus trapping when opened with .showModal(). It automatically traps focus, handles Esc dismissal, and manages backdrop rendering. However, for complex scenarios (nested modals, animated transitions, or custom styling), many developers still implement custom focus traps using JavaScript. Libraries like focus-trap, a11y-dialog, and framework-specific solutions (React Aria, Vue A11y Dialog) provide robust implementations that handle edge cases like iframes and Shadow DOM.

aria-modal="true" is an ARIA attribute that tells screen readers that content behind the dialog is inert and should not be interacted with. It's a semantic/declarative hint for assistive technology. A focus trap is the programmatic enforcement — it physically prevents keyboard focus from leaving the dialog by intercepting Tab keystrokes. Both work together: aria-modal informs the screen reader about the modal context, while the focus trap ensures keyboard-only users (with or without a screen reader) cannot accidentally navigate out. Using one without the other creates an incomplete accessibility implementation.