focus-trap
Web validation
A keyboard trap happens when keyboard focus enters a component and cannot leave it. Users can move into the component with Tab, but pressing Tab, Shift+Tab, Escape, or the arrow keys never takes them back out, so the rest of the page becomes unreachable. Keyboard traps can be created intentionally or by accident. Common causes include scripts that override the default behavior of Tab or Escape without offering another way out, and complex or non-standard components, such as custom widgets, embedded editors, or third-party content, that capture every key press. For people who rely on a keyboard or a screen reader, a trap can lock them into a single component and block the rest of the page entirely.
Pass Patterns
Tab and Shift+Tab move focus freely
The component uses native, focusable elements and does not override Tab, so focus can enter it and leave it in both directions.
<div class="toolbar">
<button>Bold</button>
<button>Italic</button>
<button>Underline</button>
</div>
<a href="/next">Next page</a>A modal dialog that can be closed with Escape
Focus is intentionally kept inside the open dialog, but Escape and the Close button always provide a standard way out.
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Edit profile</h2>
<button id="close-dialog">Close</button>
</div>
<script>
const dialog = document.querySelector('[role="dialog"]');
dialog.addEventListener("keydown", (event) => {
if (event.key === "Escape") closeDialog(); // Standard way out
});
document.getElementById("close-dialog").addEventListener("click", closeDialog);
</script>Fail Patterns
Tab is blocked inside a component
The script prevents Tab's default behavior and keeps moving focus back into the same field, so keyboard users can never leave it.
<input id="search" type="text" aria-label="Search" />
<script>
document.getElementById("search").addEventListener("keydown", (event) => {
if (event.key === "Tab") {
event.preventDefault(); // Focus can never move on
}
});
</script>Focus is forced back when it leaves
A blur handler returns focus to the field every time the user tries to move away, trapping them in place.
<input id="email" type="email" aria-label="Email" />
<script>
const email = document.getElementById("email");
email.addEventListener("blur", () => email.focus());
</script>WCAG techniques
Sufficient techniques
Failure techniques
Try It Yourself
Using a keyboard
- Load the page.
- Press Tab to move focus into each component, then keep pressing Tab and Shift+Tab to move away from it.
- If focus does not leave, try Escape and the arrow keys.
Expected results: Focus can always move away from the component using standard keys, or the component tells users how to leave it.
Actual results: Focus stays stuck inside the component, and the rest of the page cannot be reached with the keyboard.
Using a screen reader
New to screen reader testing, or need a refresher?
Review this article first: Practical guides for using screen readers
- Load the page and open a screen reader.
- Move through the page with Tab and Shift+Tab.
- Listen for whether announcements keep repeating the same component.
Expected results: The screen reader announces each component in turn, and you can move past every one of them.
Actual results: The screen reader keeps announcing the same component, because focus cannot leave it.
FAQ
How does this issue relate to 2.1.2 No Keyboard Trap?
SC 2.1.2 requires that if keyboard focus can be moved into a component, it can also be moved away from it using only the keyboard. If leaving requires more than the standard keys, such as unmodified arrow keys, Tab, or Escape, users must be told how to leave. A component that holds focus with no way out fails the criterion.
Why is this issue marked as Critical?
A keyboard trap can completely block keyboard and screen reader users from reaching the rest of the page, often leaving no option but to reload or close it. Because it stops task completion outright, it is rated critical.
Is keeping focus inside a modal dialog a keyboard trap?
No. Containing focus inside an open modal dialog is intentional and expected, as long as the dialog provides a standard way out, such as the Escape key or a Close button. See focus-kept-within-the-modal. It becomes a keyboard trap only when there is no keyboard way to close the dialog or move focus out of it.
How do I fix a keyboard trap?
The fix depends on the cause. In general, avoid overriding the default behavior of navigation keys such as Tab and Escape, use native HTML elements where possible, and use complex or non-standard components only when necessary. If a component must use non-standard keys to exit, tell users which keys to press.
Standards and Regulations
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 2.1.2 No Keyboard Trap (A) | If keyboard focus can be moved to a component using a keyboard interface, focus can be moved away from that component using only a keyboard interface, and if it requires more than unmodified arrow or tab keys, the user is advised of the method. |
| EN 301 549 | 9.2.1.2 No Keyboard Trap | Same as the WCAG text. |
| 508 Trusted Tester | 2.1.2-no-keyboard-trap, 4.C | There is no keyboard trap. |