Chapter 2 of 8 · 6 checks · 3 min
Keyboard and focus
Everything a mouse can do must work from the keyboard, and people must always see where focus is. These checks cover the keyboard pass every release should get.
Make every function work with the keyboard alone (SC 2.1.1)Must
Why it matters and how to check
People who cannot use a mouse, including many screen reader users and people with tremors, rely on the keyboard. Menus, dialogs, carousels, date pickers, drag and drop and custom selects are where keyboard support usually breaks.
To verify, put the mouse away and complete your three most important tasks, such as sign up, search and checkout, using only Tab, Shift+Tab, Enter, Space, Escape and the arrow keys. Note every step where you get stuck or have to guess.
Let focus leave every component with the keyboard (SC 2.1.2)Must
Why it matters and how to check
WCAG 2.2 requires that if focus can move into a component, the user can move it away with the keyboard alone, and must be told how if it takes more than Tab or the arrow keys. Embedded players, code editors and third party widgets are common traps.
To verify, tab into every embedded editor, map, video player and iframe on the page, then try to tab out of it in both directions. If you cannot leave without the mouse, it is a trap. A modal dialog that keeps focus inside on purpose is fine, as long as Escape or a close button lets you out.
Show a clearly visible focus indicator on every focusable element (SC 2.4.7)Must
Why it matters and how to check
A global
outline: nonein a CSS reset leaves keyboard users unable to see where they are. Keep a strong focus style, using:focus-visibleso mouse users do not see it on click. WCAG 2.2 adds Focus Appearance (2.4.13, level AAA), which describes a good target: an indicator at least 2 CSS pixels thick with at least 3:1 contrast against the unfocused state.To verify, tab through the whole page and confirm you can always see which element has focus, including on dark sections, images and buttons that change colour on hover. Search your CSS for
outline: noneandoutline: 0and check each has a visible replacement.Example
CSS :focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }Keep the focus order the same as the reading order (SC 2.4.3)Should
Why it matters and how to check
Focus should move through the page in the order people read it. Positive
tabindexvalues and CSS that visually reorders content (such asorderin flexbox or grid placement) break this, and focus jumps around the screen.To verify, tab through each page and watch the focus move. It should go top to bottom and left to right in the order of the layout, with no jumps. Search the codebase for
tabindexvalues above 0 and remove them.Avoid
tabindex="1"or any positive tabindex- Reordering content visually with CSS while the DOM order stays different
Move focus into dialogs, return it on close and reset it on route changesShould
Why it matters and how to check
When a dialog opens, focus should move into it; when it closes, focus should return to the button that opened it. The native
dialogelement opened withshowModal()handles much of this for you. In a single page app, a route change does not reset focus the way a full page load does, so move focus to the new page heading or main region after navigation.To verify, open every dialog with the keyboard and confirm focus lands inside it, Tab stays inside it, Escape closes it and focus returns to the trigger. Then navigate between two routes with the keyboard and check that a screen reader announces the new page.