Keyboard Accessibility Checklist
Practical keyboard QA: tab order, focus visibility, Enter/Space activation, Escape, arrows for widgets, and no keyboard traps.
- accessibility
- keyboard-accessibility
If a feature can’t be operated with a keyboard alone, it fails a large set of users (motor disabilities, power users, many screen reader workflows). This checklist is what you run before shipping a widget — and what interviewers expect you to verbalize.
Docs: WCAG Keyboard, MDN keyboard-navigable widgets, APG.
Pre-flight setup
- Unplug or ignore the mouse.
- Start at the address bar; Tab into the page.
- Note a skip link if present.
- Keep a list of interactive controls.
Checklist
Focus basics
- Every interactive control is reachable via Tab (or intentional arrow model).
- Focus order matches visual reading order.
- No
tabindex> 0. - Focus is always visible (
:focus-visible). - No keyboard trap (except intentional modal traps with Escape).
Activation
- Buttons activate with Enter and Space.
- Links activate with Enter.
- Custom widgets follow APG keys.
Dialogs / menus / comboboxes
- Escape closes and restores focus.
- Arrows move within composite widgets.
- Tab behavior matches the pattern (menu vs dialog differ).
Forms
- Labels reachable; errors announced.
- Submit via keyboard.
- File inputs operable.
Media & extras
- Players have keyboard controls.
- Drag-and-drop has keyboard alternative.
- Infinite scroll has a non-scroll way to load (button).
Quick reference keys
| Key | Common use |
|---|---|
| Tab / Shift+Tab | Move between tab stops |
| Enter | Activate links/buttons |
| Space | Activate buttons; toggle checkboxes |
| Escape | Dismiss |
| Arrows | Radios, tabs, menus, listboxes |
| Home/End | First/last in composite |
Code smells during review
<div onclick="…">Save</div>
<a href="#" onclick="…">Open modal</a>
<div tabindex="0" @click="…"> <!-- no key handler -->
Prefer <button> / <a href>.
Automated vs this list
axe won’t complete this checklist. Pair with automated axe limits.
Interview out-loud answer
“I keyboard-test every flow: visible focus, logical order, Enter/Space, Escape to exit modes, and APG arrows for composites. No positive tabindex. Custom controls get full key support or we use native elements.”
Browser shortcuts collisions
Don’t override reserved browser shortcuts without strong product need. Custom Ctrl/Cmd combos should be documented and avoid stealing Tab, which must move focus. Single-page apps that hijack / for search should still leave Tab alone.
Extra practice
Write a minimal demo in a scratch file or the playground: one happy path, one failure path, and one boundary input. If you cannot exhibit a bug that the pattern prevents, you do not own the concept yet — re-read the primary docs linked below and tighten the example until the failure is obvious.
Notes from real codebases
Teams that succeed here keep the rules mechanical: lint where possible, CI for the rest, and a short human checklist for what automation cannot see. Document exceptions with an owner name and a removal date so “temporary” escapes do not become permanent architecture.
Related on this site
Further reading
Related guides
- Accessible Combobox PatternBuild or evaluate comboboxes with APG keyboard behavior, aria-expanded/activedescendant, and filterable listbox pairing.
- Accessible Forms ErrorsLabel inputs, associate errors with fields, announce failures, and avoid placeholder-only forms that break accessibility.
- Accessible Menus PatternAPG menu and menubar keyboard model — arrow navigation, escape to close, aria-expanded, and when a disclosure is enough.
- Accessible Modals PatternsModal dialogs that work: focus trap, Escape, return focus, aria-modal, and why native dialog or APG patterns beat div soup.
- Accessible Names ComputationHow browsers compute accessible names from content, labels, aria-label, and labelledby — and how that powers Testing Library queries.