Keyboard accessibility is the foundation that most other accessibility depends on. Screen reader users navigate with the keyboard. So do many people with motor disabilities, people using switch devices or voice control (which often simulate keystrokes), power users, and anyone whose trackpad just died.
If a feature can’t be reached and operated with a keyboard, those users can’t use it at all. Keyboard problems are also among the easiest to find: put your mouse away and press Tab. This guide covers the WCAG requirements, the common failures and the patterns that fix them.
Key takeaways
- Every interactive element must be reachable and operable with a keyboard alone (WCAG 2.1.1).
- Focus order must follow a logical reading order (2.4.3), and focus must always be visible (2.4.7).
- WCAG 2.2 adds Focus Not Obscured: sticky headers, banners and chat widgets must not hide the focused element.
- Use native HTML elements. A
buttonis keyboard accessible for free; a clickabledivis not. - When content changes, such as opening a dialog or deleting an item, move focus deliberately.
The WCAG criteria at a glance
| Criterion | Level | What it means in practice |
|---|---|---|
| 2.1.1 Keyboard | A | All functionality works with a keyboard |
| 2.1.2 No Keyboard Trap | A | Focus can always move away from any component |
| 2.1.4 Character Key Shortcuts | A | Single-key shortcuts can be turned off or remapped |
| 2.4.3 Focus Order | A | Focus moves in an order that preserves meaning |
| 2.4.7 Focus Visible | AA | You can always see which element has focus |
| 2.4.11 Focus Not Obscured (Minimum) | AA (new in 2.2) | The focused element isn’t completely hidden by other content |
| 2.4.13 Focus Appearance | AAA (new in 2.2) | Focus indicator is large and high-contrast enough |
| 3.2.1 On Focus | A | Receiving focus doesn’t trigger unexpected changes |
Start with native elements
The most effective keyboard accessibility technique is also the simplest: use the right HTML element.
<!-- Accessible by default: focusable, works with Enter and Space, announced as a button -->
<button type="button">Save</button>
<!-- Not accessible: not focusable, no keyboard support, no role -->
<div class="btn" onclick="save()">Save</div>To make that div behave like a real button you’d need tabindex="0", role="button", and JavaScript handling both Enter and Space. That’s three things to get right and keep right, compared with zero for a native button.
The same applies to links (a href), form controls, details and summary for disclosures, and the native dialog element for modals. Use links to go somewhere and buttons to do something.
Focus order
Focus should move through the page in an order that matches the visual and logical reading order: usually top to bottom, left to right in left-to-right languages.
Focus order problems usually come from:
- CSS reordering. Flexbox
order, grid placement or absolute positioning can make the visual order differ from the DOM order. Keep the DOM in a logical order and use CSS for layout only within reason. - Positive tabindex values.
tabindex="1"or higher forces an element to the front of the tab order and almost always creates confusion. Avoid positive tabindex entirely. - Content injected in the wrong place. A modal added at the end of the body, or a dropdown menu far from its trigger in the DOM, breaks the expected sequence.
How tabindex actually works
tabindex="0": adds an element to the natural tab order. Use it only for custom interactive widgets.tabindex="-1": makes an element focusable by script but not by Tab. Useful for headings or containers you move focus to programmatically.tabindex="1"and above: avoid.
Visible focus
If keyboard users can’t see where focus is, they’re navigating blind. The most common cause is CSS like this:
/* Please don't */
*:focus { outline: none; }Designers sometimes remove the outline because it appears on mouse click. The modern solution is :focus-visible, which browsers apply when focus should be shown, typically for keyboard users:
:focus-visible {
outline: 3px solid #1f2a8a;
outline-offset: 3px;
}A good focus indicator:
- Has at least 3:1 contrast against the surrounding colours (see my colour contrast guide)
- Is thick enough to notice, 2 to 3 pixels or more
- Uses
outlinerather than onlybox-shadow, because outlines remain visible in Windows contrast themes - Is consistent across the whole site
Focus Not Obscured (new in WCAG 2.2)
Sticky headers, cookie banners, chat buttons and “back to top” bars are everywhere, and they often cover the element that has focus. WCAG 2.4.11 requires that when an element receives focus, it isn’t entirely hidden by author-created content.
Fixes include:
scroll-padding-topon the html element, set to at least the height of your sticky header, so focused elements scroll into view below it:
html { scroll-padding-top: 5rem; }- Making cookie banners dismissible and not covering focusable content once dismissed
- Keeping floating widgets small and positioned so they don’t overlap main content
Keyboard traps
A keyboard trap happens when focus enters a component and can’t get out: an embedded video player, a third-party widget, a rich text editor or a badly built modal. WCAG 2.1.2 requires that users can always move focus away using standard keys, or that you tell them how.
Note the difference between a trap and a modal dialog: in a modal, keeping focus inside the dialog while it’s open is correct behaviour, as long as Escape or a close button lets the user leave. The native HTML dialog element, opened with showModal(), handles most of this for you.
Managing focus in dynamic interfaces
Single-page apps and interactive components change content without page loads, and focus needs to follow the user’s attention. Some rules of thumb:
| Situation | Where focus should go |
|---|---|
| Opening a modal dialog | Into the dialog (first field, or the dialog heading) |
| Closing a modal | Back to the element that opened it |
| Deleting an item from a list | To the next item, the previous item, or the list heading |
| Route change in a single-page app | To the new page’s H1 or main content |
| Form submitted with errors | To the error summary or first invalid field |
| Expanding an accordion | Stay on the trigger; content appears after it in reading order |
The worst outcome is focus being “lost”: the focused element is removed from the page and focus falls back to the top of the document. Keyboard and screen reader users then have to navigate all the way back.
Custom widgets need custom keyboard support
For complex widgets like tabs, menus, tree views, comboboxes and sliders, users expect specific keys: arrow keys to move within the widget, Tab to move out, Home and End to jump. The W3C ARIA Authoring Practices Guide documents the expected keyboard interaction for each pattern. If you build one of these, follow it closely and test it with a screen reader. And read the first rule of ARIA before you start.
A five-minute keyboard test
- Click in the browser address bar, then press Tab repeatedly through the whole page.
- Can you see focus at every step?
- Does focus follow a logical order?
- Can you reach and operate every link, button, menu, form field and widget? Use Enter, Space, the arrow keys and Escape.
- Is anything hidden behind a sticky header or banner when it receives focus?
- Can you open and close every dialog, menu and dropdown, with focus going to sensible places?
- Do you ever get stuck?
If you do one accessibility check this week, make it this one.
Conclusion
Keyboard accessibility comes down to a few habits: use native elements, keep the DOM in a logical order, never remove focus styles without a better replacement, keep focus visible above sticky content, and move focus deliberately when the interface changes. Get these right and you’ve solved a large share of the barriers that keyboard, screen reader and switch users face.
Further reading
- Skip Links: A Complete Guide for Developers and Designers (WCAG 2.2)
- Screen Reader Testing for Beginners: NVDA and VoiceOver
- W3C: Understanding 2.4.11 Focus Not Obscured (Minimum)
- W3C: ARIA Authoring Practices Guide


Pingback: Colour Contrast Accessibility Guide: WCAG Ratios, Tools and Fixes
Pingback: Screen Reader Testing for Beginners: NVDA and VoiceOver Guide