Focus Traps — Implementing Focus Trapping in Modal Dialogs
In this tutorial, you will learn about Focus Traps. We cover key concepts, practical examples, and best practices to help you master this topic.
Focus trapping ensures keyboard focus stays within a modal dialog, cycling between the first and last focusable element until the dialog is dismissed, preventing keyboard traps outside the modal.
In this tutorial, you'll learn to implement Keyboard Navigation focus traps.
What You'll Learn
By the end of this lesson, you'll understand the focus trapping algorithm, how to implement it for modals, and how to handle Enter, Escape, and Tab cycling.
Why It Matters
Without focus trapping, keyboard users can Tab out of a modal into the background, losing their place and causing confusion about which context is active.
Real-World Use
Doda Browser's settings dialog uses a focus trap to keep users within the dialog until they explicitly close it.
Focus Trap Flow
flowchart TD
A[Modal opens] --> B[Find first focusable element]
B --> C[Focus first element]
C --> D[Tab key pressed]
D --> E{At last element?}
E -->|No| F[Move to next element]
E -->|Yes| G[Cycle to first element]
G --> H{Shift+Tab at first?}
H -->|Yes| I[Cycle to last element]
H -->|No| J[Continue normal cycling]
Implementing a Focus Trap
function trapFocus(container) {
const focusableElements = container.querySelectorAll(
'a[href], button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
container.addEventListener('keydown', (event) => {
if (event.key !== 'Tab') return;
if (event.shiftKey) {
if (document.activeElement === firstElement) {
event.preventDefault();
lastElement.focus();
}
} else {
if (document.activeElement === lastElement) {
event.preventDefault();
firstElement.focus();
}
}
});
firstElement.focus();
}
Modal Focus Trap
function openModal(modal) {
modal.hidden = false;
trapFocus(modal);
document.getElementById('page-content').inert = true;
}
function closeModal(modal) {
modal.hidden = true;
document.getElementById('page-content').inert = false;
document.getElementById('open-modal-btn').focus();
}
Escape Key Handling
modal.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closeModal(modal);
}
});
Common Mistakes
- Not cycling focus: Focus moves out of the modal on Tab at the last element.
- Forgetting Shift+Tab cycling: Shift+Tab at the first element should go to the last.
- Not focusing the first element on open: Users must manually Tab into the modal.
- Not restoring focus on close: Focus is lost or goes to an unexpected place.
- Trapping focus on non-modal elements: Only modal dialogs need focus trapping.
Practice and Challenge
1. What is a focus trap? A pattern that keeps keyboard focus within a container element.
2. When should focus trapping be used? In modal dialogs, side panels, and any interface that prevents background interaction.
3. What happens when Tab is pressed on the last focusable element? Focus cycles to the first focusable element.
4. What happens when Escape is pressed? The modal closes and focus returns to the trigger element.
5. Challenge: Implement a focus trap for a modal dialog. Verify Tab cycling, Shift+Tab cycling, and Escape dismissal.
FAQ
Mini Project
Build a modal dialog with a complete focus trap. Include: Tab cycling, Shift+Tab cycling, Escape to close, focus on open, and focus restoration on close.
What's Next
Continue to Visible Focus to learn about designing visible focus indicators.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro