Focus Trap Modal
title: "Focus Trap — Keeping Keyboard Focus Inside the Modal" description: "Learn how to implement a focus trap that keeps keyboard focus cycling within the modal dialog, preventing users from tabbing to background content." weight: 5 date: 2026-06-28 lastmod: 2026-06-28 tags: [accessibility, modals]
A focus trap ensures that when a modal is open, pressing Tab cycles through elements inside the modal only, never reaching the background page.
## What You'll Learn
How to implement a focus trap with JavaScript, identify focusable elements, and handle first and last element edge cases.
## Why It Matters
Without a focus trap, keyboard users can Tab out of the modal to background content, losing context and potentially causing unexpected actions.
## Real-World Use
A modal asks "Are you sure you want to delete?" with Cancel and Delete buttons. The user tabs through both buttons. At the Delete button, the next Tab cycles back to Cancel instead of reaching the background page.
## Focus Trap Implementation
```javascript
function trapFocus(element) {
const focusable = element.querySelectorAll(
'a[href], button, textarea, input, select, [tabindex]:not([tabindex="-1"])'
);
const firstFocusable = focusable[0];
const lastFocusable = focusable[focusable.length - 1];
element.addEventListener('keydown', function(e) {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
if (document.activeElement === firstFocusable) {
e.preventDefault();
lastFocusable.focus();
}
} else {
if (document.activeElement === lastFocusable) {
e.preventDefault();
firstFocusable.focus();
}
}
});
firstFocusable.focus();
}
Usage
const dialog = document.getElementById('my-modal');
dialog.addEventListener('keydown', focusHandler);
function focusHandler(e) {
if (e.key !== 'Tab') return;
const focusable = Array.from(
dialog.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
).filter(el => !el.disabled && el.offsetParent !== null);
const first = focusable[0];
const last = focusable[focusable.length - 1];
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
Common Mistakes
1. Focus trap not enabled on open
The focus trap must be attached when the modal opens, not on page load.
2. Focus trap not removed on close
The focus trap event listener must be removed when the modal closes to restore normal tab behavior.
3. Hidden focusable elements in the trap
Screen-reader-only elements or invisible elements should have tabindex="-1" to exclude them from the trap.
4. No initial focus
When the modal opens, focus must move to the first focusable element or the primary action button.
5. Focus trap with dynamic content
If modal content changes dynamically, recalculate the focusable elements.
Practice Questions
1. What keyboard key does a focus trap intercept? The Tab key (and Shift+Tab for reverse navigation).
2. What happens when the user tabs past the last focusable element? Focus wraps back to the first focusable element inside the modal.
3. Why must the focus trap be removed on close? To restore normal page tabbing behavior for elements outside the modal.
Challenge: Implement a focus trap for a modal with 5 focusable elements. Verify wrapping behavior and removal on close.
FAQ
Mini Project
Build a modal component with a complete focus trap. Include input fields, buttons, and links inside the modal. Verify Tab wrapping works correctly.
What's Next
Learn where to set Initial Focus when a modal opens to provide the best user experience for keyboard and screen reader users.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro