Level A Operable WCAG 2.0+

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.

Web Content Accessibility Guidelines (WCAG) 2.2

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.

Critical Issue: Keyboard traps are one of the most severe accessibility barriers. They make content completely unusable for keyboard-only users.

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

Good Example - Accessible Modal
<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

Good Example - Editor with Exit Instructions
<!-- 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 Examples
<!-- 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

  1. Tab through entire page: Note every interactive element you can focus
  2. Try to leave each element: Use Tab, Shift+Tab, Escape, arrow keys
  3. Test modals: Open each modal and try to close it with keyboard
  4. Test embedded content: iframes, video players, maps, etc.
  5. 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

Additional Resources