What the Keyboard Navigation Auditor does
This auditor reads a page's HTML and works out the order in which Tab visits its controls, then flags what will trip up keyboard users: positive tabindex values that hijack the order, click handlers on elements that cannot be focused, focusable links hidden inside aria-hidden regions, a missing or broken skip link, dialogs with no name or no aria-modal, and focus outlines removed inline. It then gives you a short manual checklist to carry out in your own browser and records your results alongside the automated ones.
It never declares a page keyboard accessible on its own. Markup can show that a control is reachable; only pressing the keys shows whether it responds, whether focus is visible and whether a dialog lets you out again. The report keeps the two apart. This is different from the Keyboard Tester, which checks the keys of a physical keyboard.
How to use it
- Paste the page's HTML, or enter a public URL and press Fetch page HTML. For script-built pages, paste the rendered DOM from DevTools.
- Press Audit keyboard access. The computed tab order lists every tab stop in the sequence the browser uses: positive tabindex values first in ascending order, then everything else in source order. A radio group counts as one stop.
- Fix the automated problems first. Each one names the element and the change, such as replacing a clickable div with a button.
- Open the real page, put the mouse aside, and work through the ten manual checks with Tab, Shift+Tab, Enter, Space, the arrow keys and Escape. Mark each pass, fail or not applicable, with a note.
- Download the Markdown or CSV report. It lists automated findings, the tab order and your manual results, clearly labelled.
Reading the results
The summary only says "All manual checks recorded as passing" when you have recorded every manual check and none failed, and no automated problem remains. Until then it says the result is not proven - deliberately, because the most common keyboard failures (no visible focus, keyboard traps, widgets that ignore Enter) are invisible in markup.
A positive tabindex is reported as a problem even when the order looks right today, because it pulls elements ahead of everything else on the page and breaks as soon as the layout changes. tabindex="0" adds an element to the natural order and tabindex="-1" makes it focusable by script only; both are fine when used on purpose.
"Hidden" in the tab order means hidden in the markup - the hidden attribute, inline display:none, a closed dialog, or aria-hidden. Elements hidden by a stylesheet are not detected, so an off-screen menu that still takes focus will only show up in the manual checks.
Worked example: a shop header with a newsletter pop-up
The shop example has a search box with tabindex="1", eight category links, a cart that is a div with onclick, an account control that is a span role="button", a checkout link inside an aria-hidden drawer, and a newsletter pop-up built as div role="dialog" with a close control that is another clickable div.
The computed order starts with the search box, because tabindex 1 beats everything else, then the logo, the eight category links, the two products, the Add to bag button and the hidden Checkout link: 13 stops with no skip link. The cart, the account control and the pop-up's close control never appear, so a keyboard user cannot open the cart, sign in or dismiss the pop-up at all. The checkout link is reachable but announced as nothing, because its container is aria-hidden.
The fixes: remove the tabindex from the search box, make cart and account real <button> elements, give the drawer the inert attribute while it is closed, use <dialog> with showModal() for the pop-up with a real close button and aria-labelledby, add a skip link, and style :focus-visible instead of removing the outline. Then do the manual checks - especially that Escape closes the pop-up and focus returns to where it was.
Limitations: what the result does not prove
- Static analysis cannot press keys. It cannot tell whether a control responds to Enter or Space, whether focus is visible, whether a widget traps focus or whether a custom menu supports arrow keys - those are the manual checks, and they matter most.
- It sees the HTML supplied. Event listeners added by script (addEventListener) are invisible, so a clickable div wired up in JavaScript is only caught if it has an inline handler or a common framework attribute such as ng-click or @click.
- CSS-driven visibility and order (display, visibility, order, position off-screen) is not evaluated beyond inline style attributes.
- A good result here does not cover screen reader behaviour, zoom and reflow, or touch access.
Privacy: where your data goes
The analysis runs in your browser. If you choose to load a public URL instead of pasting, a2z.tools fetches that address read-only and returns the text to your tab; private and internal addresses are refused and nothing is stored. Session recording and tag-manager scripts are switched off on this page.
Standards and sources
- WCAG 2.2 - checked 19 Sep 2026
- W3C - Understanding WCAG 2.2 Success Criterion 2.1.1 Keyboard
- W3C - Understanding WCAG 2.2 Success Criterion 2.4.3 Focus Order
- W3C - Understanding WCAG 2.2 Success Criterion 2.4.7 Focus Visible
- W3C - Understanding WCAG 2.2 Success Criterion 2.4.1 Bypass Blocks
- WHATWG HTML - Sequential focus navigation and the tabindex attribute
- W3C WAI-ARIA Authoring Practices - Developing a keyboard interface
Frequently asked questions
How do I test a website with only the keyboard?
Put the mouse away and press Tab from the address bar. Every link, button and field should receive focus in a sensible order, with a visible indicator. Activate links with Enter, buttons with Enter or Space, use arrow keys inside menus, tabs and radio groups, and check you can always leave with Tab or Escape. The manual checklist on this page follows those steps.
Why is a positive tabindex bad?
Any element with tabindex 1 or higher is visited before every element with tabindex 0 or none, whatever its position on the page. The order stops matching what people see, and every new component needs renumbering. Use tabindex 0 and put the elements in the right order in the source instead.
What is a skip link and do I need one?
A skip link is the first focusable element on the page, usually visible only on focus, that jumps past the header to the main content. WCAG 2.4.1 requires a way to bypass repeated blocks; landmarks meet it for screen reader users, but sighted keyboard users still benefit from a skip link when the header has many links.
Why can't my clickable div be used with a keyboard?
A div is not focusable, so Tab skips it, and it does not fire click on Enter or Space. Adding role=button alone changes only what screen readers announce. Use a real button element, which gets focus, keyboard activation and the right role for free.
Does this tool prove WCAG 2.1.1 conformance?
No. It finds markup patterns that make keyboard access impossible or confusing. Whether everything actually works from the keyboard can only be shown by operating the page, which is why the manual checks exist and why the report never claims conformance from the automated part.
What should happen to focus when a dialog opens?
Focus should move into the dialog - to its first control, or to the dialog itself - stay inside it while it is open, and return to the control that opened it when it closes. Escape should close it. The native dialog element opened with showModal() handles most of this; a div with role=dialog needs script to do it all.
How is this different from the Keyboard Tester tool?
The Keyboard Tester checks physical hardware: it lights up each key you press so you can find a dead or sticky key. This auditor checks web pages: whether people who rely on a keyboard, switch device or voice control can reach and operate everything on them.
Last reviewed by the A2Z.Tools team against the sources listed above.