Success Criterion 2.1.2: No Keyboard Trap
Official W3C Definition
If keyboard focus can be moved to a component of the page using a keyboard interface, then focus can be moved away from that component using only a keyboard interface, and, if it requires more than unmodified arrow or tab keys or other standard exit methods, the user is advised of the method for moving focus away.
Why This Criterion Matters
A keyboard trap occurs when a user can navigate into a component but cannot navigate out using standard keyboard controls. This completely blocks keyboard users from accessing the rest of the page, forcing them to close the browser or use a mouse they may not be able to use.
Who Benefits
Blind Users
Cannot use mouse to escape from trapped elements.
Motor Disabilities
May only be able to use keyboard or switch devices.
Keyboard Users
All keyboard users benefit from trap-free navigation.
Voice Control Users
Voice navigation relies on keyboard-like interactions.
How to Meet This Criterion
Technique 1: Modal Dialogs with Escape Key
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h2 id="modal-title">Confirm Action</h2>
<p>Are you sure you want to proceed?</p>
<button onclick="closeModal()">Cancel</button>
<button onclick="confirmAction()">Confirm</button>
</div>
<script>
// Close modal on Escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && modalIsOpen()) {
closeModal();
}
});
// Trap focus inside modal while open
function trapFocus(element) {
const focusableElements = element.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
element.addEventListener('keydown', function(e) {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
});
}
</script>
Technique 2: Rich Text Editors
<!-- Rich text editor with escape instructions -->
<div class="editor-wrapper">
<p class="editor-instructions">
Press Escape then Tab to exit the editor.
</p>
<div role="textbox"
aria-multiline="true"
aria-label="Content editor. Press Escape then Tab to exit."
contenteditable="true">
</div>
</div>
<script>
const editor = document.querySelector('[contenteditable]');
let escapePressed = false;
editor.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
escapePressed = true;
setTimeout(() => escapePressed = false, 1000);
}
if (e.key === 'Tab' && escapePressed) {
// Allow Tab to exit the editor
e.stopPropagation();
}
});
</script>
<!-- Bad: Modal with no escape method -->
<div class="modal" onclick="event.stopPropagation()">
<!-- No close button, no escape key handler -->
<p>You're trapped here!</p>
</div>
<!-- Bad: Plugin that traps focus -->
<iframe src="video-player.html">
<!-- Plugin captures all keyboard input -->
</iframe>
<!-- Bad: Infinite tab loop -->
<script>
// Forces focus to stay on element
element.addEventListener('blur', () => element.focus());
</script>
Common Failures to Avoid
| Failure | Problem | Solution |
|---|---|---|
| Modal without close mechanism | Focus trapped inside modal | Add close button and Escape key handler |
| Third-party plugins that trap focus | User stuck in embedded content | Choose accessible plugins or provide skip mechanism |
| Forcing focus back to element | User cannot move past element | Allow natural focus movement |
| Complex widgets without exit instructions | Non-standard escape method unknown | Document and announce exit method |
| Preventing default Tab behavior | Can't tab out of component | Only modify Tab within controlled widgets |
Testing Methods
Manual Testing Steps
- Tab through entire page: Note every interactive element you can focus
- Try to leave each element: Use Tab, Shift+Tab, Escape, arrow keys
- Test modals: Open each modal and try to close it with keyboard
- Test embedded content: iframes, video players, maps, etc.
- Check non-standard exits: If special keys needed, are they documented?
Red Flags to Watch For
- Tab key cycles infinitely within a small area
- Cannot close modal/dialog with keyboard
- Focus disappears (goes to body but not next element)
- Third-party widgets that capture all keyboard input
- Rich text editors or code editors without exit method
Related Criteria
2.1.1 Keyboard
All functionality keyboard accessible
2.4.3 Focus Order
Logical focus sequence