Many people do not use a mouse. Some have motor disabilities and rely on the keyboard or on devices that emulate it, such as sip-and-puff sensors or switches; others use a screen reader, which is driven from the keyboard; others are simply expert users who move faster without taking their hands off the keys. If an interface only works with a pointer, it is a wall for all of these people.
The good news is that keyboard navigation can be checked in a few minutes and can almost always be fixed with targeted changes.
How keyboard navigation works
The basic commands are few, and it is worth knowing them before running any test:
| Key | Typical action |
|---|---|
| Tab | Moves to the next interactive element |
| Shift + Tab | Moves back to the previous element |
| Enter | Activates a link or a button |
| Space bar | Activates a button, ticks a checkbox, scrolls the page |
| Arrow keys | Move within a group: options, menus, tabs, sliders |
| Esc | Closes modal dialogs, menus and suggestions |
A guiding principle: Tab moves between components, the arrow keys move within a composite component. A group of ten radio buttons should not require ten presses of Tab.
Focus must be visible
Focus is the indicator showing which element will receive the next command. Without it, keyboard users are navigating blind. WCAG success criterion 2.4.7 (level AA) requires focus to be visible; WCAG 2.2 added criterion 2.4.11, which requires that the focused element is not entirely hidden by other content, such as a sticky bar at the bottom of the page.
The most common mistake is removing the browser's default outline because it is «ugly», without replacing it with anything. The right fix is to design one that matches the site's style:
:focus-visible {
outline: 3px solid #1a5fb4;
outline-offset: 2px;
}
The :focus-visible pseudo-class shows the indicator when it is needed, that is during keyboard navigation, and generally not after a mouse click on a button. This satisfies both those who want visual tidiness and those who need the signal.
A few tips for a good indicator:
- at least 2 pixels thick, with good contrast against both the element and the background;
- do not rely only on a slight change in text colour;
- check that it stays visible on dark backgrounds, images and coloured buttons.
A logical tab order
Focus should follow an order that makes sense, usually the reading order: top to bottom, left to right. Problems arise when the visual order and the order in the code diverge, for example when a CSS layout visually moves a block that stays elsewhere in the code.
The tabindex attribute with positive values is almost always a bad idea: it creates a parallel order that is hard to maintain. The only values you really need are 0, to make a custom element reachable, and -1, to make it focusable only by script.
Elements that must be reachable
A control that works with the mouse but cannot be reached with Tab is a serious defect. The classic case is a div with a click handler instead of a real button. The native button gives you focus, activation with Enter and Space and the correct role for screen readers for free; the div gives you none of that.
Pay particular attention to:
- dropdown menus that open only on mouse hover;
- carousels with arrows that cannot receive focus;
- clickable icons with no real interactive element behind them;
- content that appears on hover, such as tooltips or previews.
Skip links and modal dialogs
On a page with a long menu, keyboard users have to go through dozens of links before reaching the content. A skip link, a «Skip to main content» link that appears as the first element on the first Tab, solves the problem with a few lines of code.
Modal dialogs need more care. When a modal opens, focus must move inside it; while it is open, Tab must not escape to the page underneath; Esc must close it; when it closes, focus must return to the button that opened it. The HTML dialog element opened with showModal() handles much of this behaviour natively.
The ten-minute test
In my work this is one of the first checks I run on any site, because it is quick and reveals a lot:
- Put the mouse aside and load the page.
- Press Tab repeatedly and watch: is the focus always visible?
- Does the order follow the logic of the page?
- Can you use menus, forms, filters and modal dialogs?
- Is there a point where focus gets trapped with no way out?
- Can you complete the main task, such as a purchase or a sign-up?
If any of these steps fails, the problem also affects people using a screen reader, voice control or an alternative input device.
In short
- Many users depend on the keyboard: everything you can do with a mouse must be possible without one.
- Focus must always be visible: customise it with
:focus-visible, never remove it. - Tab order must follow reading order; avoid positive
tabindexvalues. - Using native elements such as
buttonanddialogsolves most problems. - A ten-minute test without a mouse exposes the most serious defects.