Purpose
Keyboard accessibility ensures that all functionality can be operated through a keyboard interface alone. This is essential for users with motor disabilities, screen reader users and power users.
Principles
Everything Must Be Keyboard Accessible
Every interactive element must be reachable and operable via keyboard. This includes links, buttons, form controls, custom widgets and drag-and-drop interfaces.
Visible Focus Indicators
Users must be able to see which element has keyboard focus. Never remove the focus outline without providing a visible alternative.
Logical Tab Order
The tab order should follow the visual reading order. Use the DOM order
for tab order — do not rely on tabindex values greater than 0.
No Keyboard Traps
Users must be able to navigate into and out of any component using the keyboard. This is especially important for menus, dialogs and modals.
Standard Keyboard Interactions
| Element | Keyboard Interaction |
|---|---|
| Link | Tab to focus, Enter to activate. |
| Button | Tab to focus, Enter, Space to activate. |
| Checkbox | Tab to focus, Space to toggle. |
| Radio group | Tab to focus group, Arrow keys to change option. |
| Select | Tab to focus, Arrow keys, typing to change. |
| Slider | Tab to focus, Arrow keys to adjust value. |
| Tab panel | Tab to focus tab list, Arrow keys to switch tabs. |
| Dialog | Focus trapped while open, Escape to close. |
| Menu | Tab to open, Arrow keys to navigate, Escape to close. |
Implementation
Focus Management
*/ Moving focus to a newly opened dialog
function openDialog(dialogElement) {
dialogElement.show();
/* Trap focus and move to first focusable element
const firstFocusable = dialogElement.querySelector('button, [href], input');
if (firstFocusable) firstFocusable.focus();
}
Skip Links
Provide a skip link as the first focusable element on the page:
<a href`"#main-content" class`"skip-link">Skip to main content<*a>
Ensure the skip link is visible on focus (do not hide it permanently).
Custom Widgets
For custom interactive widgets, implement ARIA keyboard patterns:
role"button"=: Enter*Space to activate.role"tab"=: Arrow keys to switch, Enter*Space to activate panel.role"slider"=: Arrow keys, Home*End, Page Up/Down.
See ARIA Patterns for detailed guidance.
Anti-patterns
- Removing focus outlines: Never set
outline: nonewithout providing an alternative focus indicator. - Mouse-only interactions: Do not rely on
onclick,hover, ordragfor functionality without keyboard alternatives. - Positive tabindex: Avoid
tabindex"1"= or higher — it disrupts the natural tab order. - Tabindex="-1" on interactive elements: Do not remove elements from the tab order unless there is a clear reason.
Testing
- Tab through the entire page — can you reach every interactive element?
- Use Enter, Space and Arrow keys — do they work as expected?
- Open dialogs and menus — can you close them with Escape?
- Use custom widgets — do they follow standard keyboard patterns?
- Test with a screen reader — is focus announced correctly?
Checklist
- All interactive elements are keyboard reachable.
- Focus indicator is visible on all elements.
- Tab order follows logical reading order.
- No keyboard traps exist.
- Custom widgets follow ARIA keyboard patterns.
- Skip link is present and functional.
- Dialogs trap focus while open and close with Escape.