Accessible Focus Trapping

8.0.1 · active · verified Tue Apr 21

focus-trap is a vanilla JavaScript library designed to trap keyboard focus within a specified DOM node, essential for building accessible UI components like modals, dialogs, and sidebars. It ensures that users navigating with keyboard (Tab, Shift+Tab) or screen readers cannot escape the designated area, enhancing accessibility. The current stable version is 8.0.1, with releases occurring as needed for bug fixes (patch), new features (minor), and breaking changes (major). Key differentiators include its lightweight, framework-agnostic nature, robust handling of nested traps (pausing/unpausing), and its reliance on the well-maintained `tabbable` library for determining focusable elements. It handles initial focus, tabbing within the trap, blocking clicks outside, and restoring focus on deactivation. It explicitly supports modern desktop browsers and offers UMD builds for environments without bundlers.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates creating, activating, and deactivating a focus trap for a modal dialog, including managing visibility and returning focus.

import { createFocusTrap } from 'focus-trap';

const modalElement = document.getElementById('my-modal');
const openButton = document.getElementById('open-modal-button');
const closeButton = document.getElementById('close-modal-button');

let focusTrapInstance: ReturnType<typeof createFocusTrap> | null = null;

function openModal() {
  if (modalElement) {
    modalElement.style.display = 'block';
    focusTrapInstance = createFocusTrap(modalElement, {
      onDeactivate: () => {
        if (modalElement) modalElement.style.display = 'none';
        openButton?.focus(); // Return focus to the element that opened the modal
      },
      initialFocus: closeButton || undefined, // Optionally focus the close button first
    });
    focusTrapInstance.activate();
  }
}

function closeModal() {
  if (focusTrapInstance) {
    focusTrapInstance.deactivate();
    focusTrapInstance = null;
  }
}

openButton?.addEventListener('click', openModal);
closeButton?.addEventListener('click', closeModal);

// Example: simulate opening a modal after a delay
setTimeout(openModal, 1000);

view raw JSON →