Why keyboard accessibility matters
Many users cannot use a mouse and rely on keyboard (or keyboard-emulating devices):
- Motor disabilities: Users with limited fine motor control
- Blind users: Screen reader users navigate with keyboard
- Repetitive strain injuries: Keyboard is often easier than mouse
- Switch device users: Devices emulate keyboard input
- Power users: Many prefer keyboard for efficiency
WCAG requirement: All functionality must be operable through a keyboard interface (2.1.1 Keyboard).
Essential keyboard interactions
| Key | Function |
|---|---|
| Tab | Move to next focusable element |
| Shift + Tab | Move to previous focusable element |
| Enter | Activate links, buttons, submit forms |
| Space | Activate buttons, toggle checkboxes |
| Arrow keys | Navigate within components (menus, sliders, tabs) |
| Escape | Close modals, cancel actions |
| Home / End | Jump to first/last item in a list |
Focus indicators
WCAG 2.4.7 requires that keyboard focus is visible. Users must be able to see which element they're on.
Good focus indicators
- High contrast outline (not just color change)
- Visible on all backgrounds
- At least 2px thick
- Consistent across the site
CSS focus styles
/* Good focus style */
:focus {
outline: 3px solid #0C234B;
outline-offset: 2px;
}
/* Or use focus-visible for keyboard-only focus */
:focus-visible {
outline: 3px solid #0C234B;
outline-offset: 2px;
}
/* NEVER do this: */
:focus {
outline: none; /* ❌ Removes focus indicator! */
}
Focus management requirements
- Never remove focus outlines without providing alternative
- Ensure focus is visible on all backgrounds (light and dark)
- Focus should not be obscured by sticky headers or modals (WCAG 2.4.11)
Tab order
Tab order should follow a logical reading order (typically left-to-right, top-to-bottom in English).
Maintaining natural tab order
- Use semantic HTML elements in logical order
- Avoid using
tabindexvalues greater than 0 - Test by tabbing through the page
tabindex values
| Value | Effect | Use case |
|---|---|---|
tabindex="0" |
Makes element focusable in natural order | Custom interactive elements |
tabindex="-1" |
Focusable by script only, not Tab key | Modal dialogs, error messages |
tabindex="1+" |
Overrides natural order | ⚠️ Avoid — causes confusion |
Avoiding keyboard traps
WCAG 2.1.2: Users must be able to navigate away from any component using standard keyboard.
Common trap scenarios
- Modal dialogs that don't allow Tab to exit
- Embedded content (iframes, video players) that capture keyboard
- Rich text editors
- Interactive maps
Solutions
- Modal dialogs: Allow Escape to close
- Embedded content: Ensure Tab moves past the embed
- Provide clear instructions for exiting complex widgets
- Test thoroughly by tabbing through
Keyboard-accessible elements
Natively keyboard accessible
These HTML elements are keyboard accessible by default:
<a href="...">— Links<button>— Buttons<input>— Form inputs<select>— Dropdown menus<textarea>— Text areas
Require additional work
These need tabindex and keyboard event handlers:
<div onclick="...">— Use<button>instead!- Custom dropdowns and menus
- Drag-and-drop interfaces
- Custom sliders and controls
Making custom elements keyboard accessible
<!-- ❌ Bad: div used as button -->
<div onclick="doAction()">Click me</div>
<!-- ✓ Good: use actual button -->
<button onclick="doAction()">Click me</button>
<!-- If you must use div, add keyboard support -->
<div role="button" tabindex="0"
onclick="doAction()"
onkeydown="if(event.key==='Enter'||event.key===' ')doAction()">
Click me
</div>
Skip links
Skip links allow keyboard users to bypass repetitive content (navigation) and jump to main content.
Implementation
<!-- Add as first element in body -->
<a href="#maincontent" class="skip-link">Skip to main content</a>
<!-- Add id to main content -->
<main id="maincontent">
...
</main>
<!-- CSS for skip link -->
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #0C234B;
color: white;
padding: 8px;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
Testing keyboard accessibility
Manual testing process
- Put mouse aside — Only use keyboard
- Tab through entire page — Can you reach everything?
- Check focus visibility — Can you always see where you are?
- Check logical order — Does tab order make sense?
- Test all interactions — Can you activate buttons, submit forms?
- Test complex widgets — Menus, modals, sliders, carousels
- Check for traps — Can you always Tab away?
Tools
- Accessibility Insights: Tab Stops feature visualizes tab order
- Browser DevTools: Focus indicator testing
- WAVE: Shows errors related to keyboard access
Keyboard accessibility checklist
- ☐ All interactive elements reachable by Tab
- ☐ Focus indicator always visible
- ☐ Tab order matches visual/reading order
- ☐ No keyboard traps
- ☐ Enter/Space activates buttons and links
- ☐ Escape closes modals and menus
- ☐ Skip link provided
- ☐ Custom widgets follow ARIA patterns
- ☐ Focus not obscured by sticky elements
Resources
- WCAG Understanding 2.1.1 Keyboard
- ARIA Authoring Practices Guide — Keyboard patterns for widgets
- WebAIM: Keyboard Accessibility
- Focus Management Guide
- Web & Apps Hub