Recipe: Modal + focus trap design

A lightweight pattern for trapping keyboard focus inside an overlay without third-party libraries.

Problem

When a modal opens, users who navigate via keyboard can accidentally tab into background content. The focus must stay inside the modal until it is dismissed.

Core technique

  1. Render two sentinel <div tabIndex=0 /> elements — one before and one after the modal content.
  2. On onFocus of the first sentinel, move focus to the last focusable element inside the modal.
  3. On onFocus of the last sentinel, move focus back to the first focusable element.
  4. Store the previously focused element on open and restore it on close.

Accessibility checklist

  • Escape key closes the modal.
  • aria-modal="true" on the overlay container.
  • role="dialog" with an aria-labelledby pointing to the heading.
  • Inert background content while the modal is open.

When to use

This pattern fits confirmation dialogs, settings panels, and lightbox galleries. For complex multi-step flows consider a dedicated route instead.