Focus Trap
Problem
Keyboard users can tab out of modal dialogs and interact with content behind the overlay that’s visually hidden. Focus escapes the modal, reaching buttons and links that shouldn’t be accessible. Users must tab through all background content to cycle back to the modal, breaking the modal’s purpose of focused interaction.
Solution
Contain keyboard navigation within modals or dialogs by cycling focus between interactive elements and preventing tab from escaping. This keeps keyboard users engaged with the active context and matches how these overlays trap mouse interaction.
Example
This example demonstrates trapping keyboard focus within a modal by cycling between the first and last focusable elements.
function Modal({ children, onClose }) {
// Track references to first and last focusable elements
const firstElement = useRef();
const lastElement = useRef();
const trapFocus = (e) => {
if (e.key === 'Tab') {
// Shift+Tab at first element: cycle to last
if (e.shiftKey && document.activeElement === firstElement.current) {
lastElement.current.focus();
e.preventDefault();
// Tab at last element: cycle to first
} else if (!e.shiftKey && document.activeElement === lastElement.current) {
firstElement.current.focus();
e.preventDefault();
}
}
};
return <div onKeyDown={trapFocus}>{children}</div>;
}
Benefits
- Improves accessibility by preventing keyboard users from accessing hidden content behind modals.
- Creates consistent interaction model where focus behavior matches visual presentation.
- Meets
WCAGrequirements for modal dialogs and overlay components. - Reduces user confusion by keeping focus within the active context.
Tradeoffs
- Requires tracking first and last focusable elements, adding implementation complexity.
- Can trap users if the modal lacks a clear escape method like Escape key or close button.
- May conflict with browser extensions or assistive technology that manage focus.
- Needs careful testing across different browsers and assistive technologies.