Keyboard traps in editors and embedded widgets
A text editor takes over the Tab key to indent, so Tab and Shift + Tab can no longer leave it.
The problem
Keyboard users who Tab into the editor cannot Tab out of it, so the rest of the page is out of reach.
A form has a Notes editor followed by a Save note button. Tab into the editor and type. Press Tab to move on to Save note: the editor indents the line instead. Press Shift + Tab to go back: it indents again. Nothing on the keyboard moves focus out of the editor, so Save note and the rest of the page can't be reached.
To support indenting, a script listens for keydown on the editor, cancels every Tab with preventDefault() and inserts spaces. It never checks Shift, and it offers no other key to leave. Success criterion 2.1.2 allows a component to keep focus only when the user is told how to move it away. Here there is no way out and nothing to tell.
Anyone who uses a keyboard instead of a pointer: people with motor disabilities, screen reader users, switch and voice users whose software sends Tab, and power users. A sighted mouse user can click elsewhere and never notice. A keyboard user has to reload the page and loses what they typed.
The markup is a labelled textarea, so a static scan finds nothing wrong. The trap lives in a script that only acts on a key press, and a probe has to press Tab from inside the component to see it. AI coding tools often add Tab-to-indent because developers expect it in code editors, without the way out. Traps also hide in third-party widgets, such as consent banners, chat windows and embedded maps, whose code nobody on the team reads.
Try it
Type a note, then press Tab to leave.
Can you reach Save note with Tab, and get back out with Shift + Tab?
A recreated demo. The broken version is intentionally inaccessible.
The fix
Let Tab leave the editor, or give it a release key that the page describes in text.
- 1Tab and Shift + Tab leave the component, directly or after a release key.
- 2Describe any release key in visible text, linked with
aria-describedby. - 3Never send focus back into a component the user has just left.
html
<label for="notes">Notes</label><textarea id="notes" name="notes"></textarea><button type="submit">Save note</button>js
const editor = document.getElementById('notes');editor.addEventListener('keydown', (event) => { if (event.key !== 'Tab') return; event.preventDefault(); editor.setRangeText(' ', editor.selectionStart, editor.selectionEnd, 'end');});Every Tab, with or without Shift, is cancelled and turned into two spaces. Focus can't leave the editor with the keyboard, and the page says nothing about another key.
Remove the handler. A textarea already lets people type, and the browser moves focus out of it on Tab and Shift + Tab. This is the smallest change, and nobody has to learn a special key. If people need indentation, add an Indent button or indent automatically when they press Enter.
Both pass. Letting Tab move focus costs nothing and asks nothing of the user, so use it for notes, comments, messages and any field where indenting isn't central to the task. Keep Tab for indenting only in editors where people really write code or structured text, and then always pair it with the release key and its written instruction.
Escape often has another job, such as closing the dialog the editor sits in. If so, decide which wins, or pick a different release key and write that one down; some editors use Ctrl + M to switch Tab between indenting and moving focus. Never lock focus with a blur or focusout handler that calls focus() again, for example to force a field to be valid before leaving: that is a trap too. A modal dialog is the one place where keeping focus inside is correct; the modal-focus-management guide covers it. For third-party widgets, including ones in shadow DOM or an iframe, test the live page and report traps to the vendor; if you can't fix it, load the widget only after the user opts in, or replace it.
Verify the fix
5 checks, no mouse.
Test with: Keyboard, Screen reader
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the editor or any third-party script changes.
Limits
This is a starting pattern, not a guarantee for every application. The snippet indents with two spaces and leaves out undo and outdenting. Rich-text and code editor libraries have their own Tab settings; check what yours does, then test the complete journey with a keyboard and your target assistive technology.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.