Tools
Keyboard navigation checker
A keyboard navigation checker examines the markup for the structures that break keyboard access: elements made interactive with a click handler but no keyboard role, positive tabindex values that reorder the tab sequence, focus indicators removed by CSS, and the absence of a skip link on a page with long repeated navigation. Each of these is detectable from the served HTML and CSS. Whether the page is actually operable end to end is not — that needs a person and a keyboard.
The four structures that break keyboard access
A non-native interactive element: a div or a span with a click handler. It is not focusable, so it never receives the tab sequence, and a keyboard user simply cannot activate it.
A positive tabindex value. Any element carrying one jumps ahead of every element with the default, which means the tab order stops following the visual order and becomes something nobody can predict.
A removed focus indicator. Focus still moves; there is no longer anything on screen showing where it is, which makes the page unusable for a sighted keyboard user while remaining perfectly usable with a mouse.
No skip link on a page with substantial repeated navigation, so every page is reached only by tabbing through the same set of links again.
Why positive tabindex is worse than it appears
The tab sequence visits every element with a positive value first, in ascending order, before anything with the default.
That is a global effect from a local attribute. Adding one to a single element in a component changes the order of the whole page wherever that component appears.
It also does not compose. Two components each using positive values interleave in an order neither author intended, and the result depends on which numbers each of them chose.
There is almost never a reason to use one. Reordering the tab sequence correctly means reordering the markup, which keeps the visual and focus orders in agreement by construction.
Focus indicators, and the CSS that removes them
The default focus indicator exists so a keyboard user can see where they are. Removing it without a replacement is the most common single accessibility regression introduced by a stylesheet.
It is usually removed deliberately, because the default ring appeared on mouse clicks and looked wrong, and the quickest fix was to suppress it entirely.
The modern answer is the focus-visible selector, which shows the indicator for keyboard interaction and not for mouse clicks — which is what everyone wanted in the first place.
A replacement indicator has to meet the interface-component contrast threshold against its own background. A subtle outline that nobody can see is the same defect with extra steps.
What a clean result looks like
Every interactive element a native control, or a non-native one carrying a role, a tabindex of zero and keyboard handlers for the keys that role implies.
No positive tabindex anywhere on the page.
A visible focus indicator on every focusable element, with enough contrast against its surroundings.
A skip link as the first focusable element on pages with long repeated navigation, visible when focused rather than permanently hidden.
What VeriFixScan uses
`accessibility.keyboard_navigation` examines the structures that determine whether the page can be operated from a keyboard. `accessibility.interactive_elements` detects elements made interactive without the semantics that make them reachable.
`accessibility.tabindex` reports the tab order, including positive values. `accessibility.focus_visible` reports focus indicators removed or suppressed.
`accessibility.skip_link` reports the presence and the behaviour of a skip link.
What this cannot tell you, which is the important part
Whether a keyboard trap exists. Focus entering a component and being unable to leave it is a behaviour under interaction, and no static reading of markup reveals it.
Whether the focus order makes sense. The order can be established from the markup; whether it matches the visual layout is a judgement.
Whether custom controls respond to the keys their role implies — arrow keys in a menu, escape in a dialog. The role is visible in the markup; the handler behaviour is not.
Whether focus is managed correctly when content changes: moving into a dialog on open and back to the trigger on close is invisible to a static check and is the thing that most often goes wrong.
Which is why this check narrows what to test by hand rather than replacing the test. Tabbing through a page takes a few minutes and finds what no scan can.
Frequently asked questions
- Is there ever a good reason for a positive tabindex?
- Almost never. It reorders the whole page from a single attribute and does not compose with other components doing the same. Reordering the markup achieves the intent and keeps the visual and focus orders together.
- Can I remove the focus ring if my design does not suit it?
- Only by replacing it. Use the focus-visible selector so the indicator appears for keyboard interaction and not for mouse clicks, and make sure the replacement meets the non-text contrast threshold.
- Does passing this check mean the page is keyboard accessible?
- No. It means the markup contains none of the structures that make keyboard access impossible. Traps, focus management and custom key handling all need a person with a keyboard.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website