Keyboard Navigation
Date: 2026-08-17
Everything must be reachable and operable without a mouse. It’s the cheapest accessibility test available — unplug the mouse and try to buy something — and it finds more real barriers per minute than any tool.
Keyboard navigation is operating an interface entirely through the keyboard. It’s required by WCAG, relied on by screen reader users, motor-impaired users and power users alike — WCAG.
The expected keys
Tab next focusable element
Shift + Tab previous
Enter activate a link or button
Space activate a button;
toggle a checkbox;
scroll the page
Arrows within a composite widget
— menu, tabs, radio group,
select
Escape close, cancel, dismiss
Home / End first / last in a list
These are conventions people have learned. Reimplementing them differently costs more than any novelty gains.
What’s focusable by default
FOCUSABLE, FOR FREE
<a href>
<button>
<input>, <select>, <textarea>
<details>/<summary>
elements with tabindex="0"
NOT FOCUSABLE
<div>, <span>
<a> with no href
anything with tabindex="-1"
The div-as-button problem is the root cause of most keyboard failures. Using <button> gives focusability, Enter and Space activation, the correct role and the disabled state — none of which a div has, and all of which have to be reimplemented — Semantic HTML.
tabindex
tabindex="0" focusable, in DOM order
→ for a custom control you
had to build
tabindex="-1" focusable by SCRIPT only,
not by Tab
→ for a target you want to
move focus TO
— Focus Management
tabindex="1+" NEVER
→ forces it ahead of
everything, breaks the
order globally, and
compounds with every
other positive value
See: Focus Management
Positive tabindex is one of the few genuinely absolute rules in this vault.
Focus order follows the DOM
CSS can move things VISUALLY
order, flex-direction: row-reverse,
grid placement, position
FOCUS follows the DOM, not the CSS
A visually-reordered layout produces a focus order that jumps around the screen, which is disorienting for sighted keyboard users and incoherent for everyone. Fix the DOM order rather than compensating.
Focus must be visible
/* the most damaging line in CSS */
:focus { outline: none; }Removing the outline without replacing it makes the interface unusable by keyboard — the person cannot tell where they are. It’s still present in a great many stylesheets, usually added to hide the ring on mouse click.
The correct fix:
:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
}:focus-visible applies the ring for keyboard focus and suppresses it for mouse clicks — which is what people actually wanted when they wrote outline: none — Focus Management.
Skip links
<a href="#main" class="skip-link">
Skip to main content
</a>Without one, every page requires tabbing through the entire header and navigation before reaching content — thirty or more presses per page.
It must become visible on focus. A skip link hidden with display: none is not focusable and does nothing.
Keyboard traps
A keyboard trap is a place focus can enter and cannot leave — and it ends the session, because there is no escape.
COMMON CAUSES
modals without Escape handling
embedded third-party widgets
custom date pickers
video players
chat widgets
cookie banners
Third-party embeds are the usual culprit, and they’re the ones nobody tests — a cookie banner trapping focus blocks the entire site for keyboard users before they see anything — Third-Party Scripts, Accessibility Law in the UK.
Testing it
1 unplug the mouse
2 Tab from the top of the page
3 can you reach EVERYTHING interactive?
4 can you SEE where you are at all
times?
5 can you complete a purchase?
6 can you always Escape?
Step 5 is the test that matters. Reaching every element and being unable to complete the task is still a failure.
This takes fifteen minutes and needs no software. It’s the single highest-return accessibility check available, and it also surfaces ordinary usability problems — an illogical focus order usually reflects an illogical DOM.