On this page
Keyboard access breaks most often between otherwise reasonable components: a toolbar reordered for mobile, a sticky footer covering the active button, or a menu that opens without a way to leave. Testing individual buttons is not enough. You need to follow complete tasks using only a keyboard and check that the visual sequence still makes sense.
Map the expected keyboard journey
Start with a realistic task, such as finding an invoice and downloading its receipt. Write down the expected stops before touching the interface. Include navigation, filters, results, pagination, and any confirmation panel. This turns keyboard navigation into an observable workflow rather than a vague promise that everything supports Tab.
Use the Flexbox Playground to reproduce suspicious layout ordering. Change direction and order properties while comparing the rendered layout with the source sequence. It is a layout experiment, not an accessibility scanner: its value is showing why visual placement can diverge from DOM order.
Keep the WAI keyboard guidance nearby when deciding whether an interaction really requires a pointing device. Drawing paths may have specific exceptions; opening a settings panel does not.
Establish native controls and a sensible sequence
Links navigate and buttons perform actions. Those native elements already participate in sequential focus and provide established activation behavior. A clickable paragraph does neither automatically. Replacing it with a button is usually simpler and more reliable than adding roles, key listeners, focus styles, and disabled behavior yourself.
Use Tab and Shift+Tab to move through ordinary controls. Arrow keys belong inside particular composite widgets, such as tab lists or menus, when their complete interaction model has been implemented. Do not make every navigation link arrow-key-only because the header looks like a toolbar.
<nav aria-label="Account">
<a href="/account/profile">Profile</a>
<a href="/account/billing">Billing</a>
</nav>
<button type="button">Download receipt</button>Avoid positive tabindex values. They create a separate priority sequence that becomes fragile when another component is inserted. A value of zero puts a custom focusable element into normal order; minus one allows programmatic focus without creating an ordinary Tab stop. Neither value supplies button semantics or activation behavior.
Review the MDN tabindex reference before introducing exceptions. Most ordinary pages should need very few tabindex attributes at all.
Make the active location unmistakable
A usable sequence still fails when users cannot see where they are. Inspect every focusable control, including icon buttons, pagination links, embedded widgets, and controls shown only after expansion. Visible focus needs to remain recognizable against the actual surrounding colors, not merely against the design canvas.
:where(a, button, input, select, textarea):focus-visible {
outline: 3px solid #173b85;
outline-offset: 3px;
}
html {
scroll-padding-top: 6rem;
}This is a starting point, not proof of conformance. Check whether the outline is clipped by overflow, merges into a dark panel, or disappears under an overlay. Use the contrast checker to evaluate candidate ring colors against neighboring surfaces, then verify the rendered result at browser zoom.
WCAG 2.2 distinguishes focus visibility from focus not obscured. At Level AA, authored content must not entirely hide the focused component. A practical implementation should aim higher: users should see the control and enough context to understand it. Test sticky banners both before and after scrolling, since their impact often changes during a task.
Find traps and manage transitions deliberately
A keyboard trap prevents users from leaving a component using the keyboard, unless a nonstandard exit method is communicated appropriately. Test third-party editors, maps, media players, and embedded payment fields carefully. Enter each component, operate it, and then try moving both forward and backward out of it.
Modal dialogs deliberately contain focus while open, but they also need a keyboard-operable dismissal route where dismissal is permitted. Closing should return users to a sensible location, usually the control that opened the dialog. If that control was removed, choose a stable replacement associated with the completed task.
Single-page navigation needs another explicit decision. After a route change, leaving focus on a now-detached navigation item can strand keyboard users. Move focus to an appropriate heading or main region after the destination is ready, without creating extra stops in ordinary navigation. Do not move focus on every background refresh.
Watch for focus loss after destructive actions. Deleting row four should not send the user unpredictably to the browser chrome. Prefer the next available row action, the preceding row when necessary, or a clearly labeled empty-state heading. Document the chosen rule so repeated components behave consistently.
Record failures as reproducible tasks
Run the journey once without a screen reader to isolate keyboard behavior. Then repeat important paths with the assistive technology combinations your product supports. Screen readers can change which keystrokes reach a widget, so passing a plain keyboard test is necessary but not sufficient.
For each failure, record the starting URL, viewport, browser, exact keys, expected location, and observed location. A report saying that the filter is inaccessible is difficult to verify. A report saying that pressing Tab after Apply reaches a hidden reset button gives the implementer an actionable reproduction.
Use this compact regression checklist when a component changes:
- Reach every available action without a pointer.
- Activate links with Enter and buttons with their native keys.
- Move backward through the same sequence.
- Open, operate, and leave temporary interfaces.
- Repeat after zooming and changing viewport width.
- Confirm focus remains visible after scrolling and validation.
Automated checks can flag some tabindex and semantic errors, but they cannot establish whether a sequence makes sense. The WAI keyboard testing tutorial provides a useful starting procedure. Keep findings with other accessibility work, and turn each fixed defect into a focused test rather than relying on memory during the next release.
Key takeaways
- Follow complete tasks, not isolated controls, when checking keyboard access.
- Keep source order meaningful and prefer native interactive elements.
- Make focus visible and prevent sticky content from hiding active controls.
- Define entry, exit, and restoration behavior for temporary interfaces.
- Combine repeatable manual journeys with targeted automated regression checks.
Reach designers & developers at work
Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.
Become a sponsor