2.1.1 Keyboard
All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes.
What this rule means
WCAG 2.1.1 requires that all functionality provided by the content must be operable through a keyboard interface. This means every interactive element — links, buttons, form fields, custom widgets, and media controls — must be reachable and activatable using only the keyboard. No functionality should depend exclusively on mouse-specific events like hover or drag.
The criterion allows exceptions only when the underlying function requires analog, path-dependent input that fundamentally cannot be achieved with a keyboard (such as freehand drawing). However, most common web interactions — clicking, selecting, expanding, submitting — can and must work via keyboard. The criterion explicitly prohibits requiring specific timing for individual keystrokes.
Why it matters
Keyboard accessibility is the foundation of web accessibility. Users who are blind rely on screen readers that operate through keyboard commands. Users with motor disabilities may use switch devices, sip-and-puff systems, or voice input that all translate to keyboard events. Even power users and developers frequently prefer keyboard navigation for speed and efficiency.
When interactive elements are not keyboard accessible, entire groups of users are completely locked out of functionality. This is not a minor inconvenience — it is a total barrier. A button that only responds to mouse clicks is invisible to a keyboard user, and a drag-and-drop interface without keyboard alternatives renders entire features unusable.
Related axe-core rules
- scrollable-region-focusable — Ensures that scrollable regions have keyboard access by verifying they are focusable. Without this, keyboard users cannot scroll through overflowing content.
- server-side-image-map — Ensures server-side image maps are not used. Server-side image maps depend on mouse coordinates and cannot be operated by keyboard.
How to test
Testing keyboard accessibility requires navigating through all interactive elements using only the keyboard.
- Disconnect or disable your mouse and attempt to use the page with keyboard alone.
- Press Tab to move focus forward through all interactive elements. Verify every button, link, form field, and widget receives focus.
- Press Shift+Tab to move focus backward. Confirm reverse navigation works correctly.
- Press Enter or Space to activate buttons and links. Verify they perform the expected action.
- Test custom components: dropdowns should open with Enter/Space and navigate with arrow keys, dialogs should trap focus, and tab panels should switch with arrow keys.
- Run axe-core and check for scrollable-region-focusable and server-side-image-map violations.
- Use a screen reader (VoiceOver, NVDA, JAWS) to confirm all interactive elements are announced and operable.
How to fix
Use native HTML elements whenever possible, as they come with built-in keyboard support. When custom elements are necessary, add explicit keyboard handling.
Use native interactive elements
<!-- Bad: div used as a button, no keyboard support -->
<div class="btn" onclick="submitForm()">Submit</div>
<!-- Good: native button, keyboard accessible by default -->
<button type="submit" onclick="submitForm()">Submit</button>
Add keyboard handlers to custom widgets
<!-- Bad: custom dropdown with no keyboard support -->
<div class="dropdown" onclick="toggleMenu()">
<span>Select option</span>
<ul class="menu">
<li onclick="select(1)">Option 1</li>
<li onclick="select(2)">Option 2</li>
</ul>
</div>
<!-- Good: keyboard-accessible custom dropdown -->
<div class="dropdown"
role="combobox"
tabindex="0"
aria-expanded="false"
aria-haspopup="listbox"
onkeydown="handleDropdownKey(event)">
<span>Select option</span>
<ul role="listbox" class="menu">
<li role="option" tabindex="-1"
onkeydown="handleOptionKey(event)">Option 1</li>
<li role="option" tabindex="-1"
onkeydown="handleOptionKey(event)">Option 2</li>
</ul>
</div>
Keyboard handler example
function handleDropdownKey(event) {
switch (event.key) {
case 'Enter':
case ' ':
event.preventDefault();
toggleMenu();
break;
case 'ArrowDown':
event.preventDefault();
focusNextOption();
break;
case 'ArrowUp':
event.preventDefault();
focusPreviousOption();
break;
case 'Escape':
closeMenu();
break;
}
}
Make scrollable regions focusable
<!-- Bad: scrollable container not focusable -->
<div style="overflow: auto; height: 200px;">
<p>Long content that overflows...</p>
</div>
<!-- Good: scrollable container is focusable -->
<div tabindex="0" role="region"
aria-label="Scrollable content"
style="overflow: auto; height: 200px;">
<p>Long content that overflows...</p>
</div>
Common mistakes
- Using div or span elements with click handlers but no tabindex, role, or keyboard event listeners.
- Implementing drag-and-drop functionality without providing keyboard-based reordering alternatives.
- Custom sliders or range controls that only respond to mouse movement, with no arrow key support.
- Hover-triggered menus or tooltips that have no keyboard-triggered equivalent (focus or Enter/Space).
- Click handlers on non-interactive elements that cannot receive keyboard focus.
- Using onmousedown or onmouseup without corresponding onkeydown or onkeyup handlers.
Resources
- WebAIM: Keyboard Accessibility— WebAIM
- Deque: scrollable-region-focusable Rule— Deque University