Documentation sites fail WCAG 2.1 AA in a small and predictable set of places: contrast on muted metadata, code blocks that cannot be reached or scrolled by keyboard, skipped heading levels, links that read “here”, and navigation that only works with a mouse. This checklist covers the criteria documentation actually trips on rather than all fifty.
It is organised so you can work through it in an afternoon, with the failures we see most often called out at the end.
Structure and semantics
- One
h1per page, and heading levels descend without gaps. Jumpingh2toh4breaks the outline a screen-reader user navigates by. (1.3.1 Info and Relationships, A) - Landmarks are present (
header,nav,main,footer), and there is exactly onemain. - Multiple navigations are labelled. A sidebar and a header menu both exposed as “navigation” are indistinguishable; give each an
aria-label. - A skip link is the first focusable element and is visible when focused. (2.4.1 Bypass Blocks, A)
- The page declares its language with
langonhtml. (3.1.1, A) - Lists are lists and tables are tables. A table used for layout, or a table without
thheaders, is unreadable non-visually. (1.3.1, A) - Navigation is consistent between pages. (3.2.3 Consistent Navigation, AA)
Colour and contrast
- Body text reaches 4.5:1 against its background; text at 18.66px bold or 24px normal and above needs 3:1. (1.4.3 Contrast (Minimum), AA)
- Check muted text specifically. Timestamps, breadcrumbs, captions and “last updated” lines are where documentation almost always fails, because grey-on-grey looks tasteful and measures badly.
- Check text on tinted backgrounds separately. A grey that passes on white can fail on a callout tint or a sidebar fill: the background is darker, and nothing recalculates for you.
- UI components and focus indicators reach 3:1. Borders on inputs, icon buttons, and the focus ring itself. (1.4.11 Non-text Contrast, AA)
- Colour is never the only signal. Required fields, diff highlighting and status badges need a shape, a word or an icon too. (1.4.1 Use of Color, A)
- Test both themes. If you ship a dark mode, it is a second full palette and needs its own pass.
Code themes are designed for aesthetics, not compliance. Comments in particular, conventionally a dim grey or muted green, routinely land near 3:1 on a code background. Sample every token colour in your highlighting theme, in both light and dark.
Keyboard
Unplug the mouse for this section. Every check below is done by pressing Tab, Shift + Tab, Enter, Space, Esc and the arrow keys.
- Everything interactive is reachable and operable without a pointer. (2.1.1 Keyboard, A)
- Nothing traps focus. Open the search modal and press Esc; open a dropdown and tab past it. (2.1.2 No Keyboard Trap, A)
- Focus is always visible and never removed with
outline: noneand nothing in its place. (2.4.7 Focus Visible, AA) - Focus order follows reading order. A sidebar that appears after the content in the DOM but before it visually will confuse everyone. (2.4.3, A)
- Focus moves into a modal when it opens and returns when it closes.
- Scrollable regions are keyboard-scrollable. A horizontally scrolling code block that only responds to a trackpad is unreachable; give it
tabindex="0"and an accessible name. - Custom controls expose state. A disclosure needs
aria-expanded; a tab set needsrole="tab"andaria-selected. (4.1.2 Name, Role, Value, A)
Links, images and media
- Link text makes sense alone. Screen-reader users list links out of context, so “read more” six times on a page is six identical links. (2.4.4 Link Purpose, A)
- Every image has an
alt, and decorative images have an empty one. (1.1.1 Non-text Content, A) - Screenshots are never the only source of an instruction. If the steps exist only in the picture, they do not exist. This also happens to be what makes your docs quotable by search engines.
- Diagrams have a text equivalent: a short description, or the same information in a nearby list.
- Videos are captioned, and anything auto-playing can be paused. (1.2.2, A; 2.2.2, A)
Layout and zoom
- Text scales to 200% without loss of content or function. (1.4.4 Resize Text, AA)
- The page reflows at 320px wide with no horizontal scrolling, except for genuinely two-dimensional content such as code and wide tables. (1.4.10 Reflow, AA)
- Increased text spacing does not clip anything. Line height 1.5, paragraph spacing 2em, letter spacing 0.12em. (1.4.12 Text Spacing, AA)
- Hover and focus content is dismissible and persistent. Tooltips that vanish when you move toward them fail. (1.4.13, AA)
- Respect
prefers-reduced-motionfor anything that animates.
Comfortable tap targets are good practice, but the AA-level criterion for them (2.5.8 Target Size (Minimum), 24 by 24 CSS pixels) arrived in WCAG 2.2. In 2.1 the equivalent is AAA. Worth doing either way, and worth knowing which standard you are claiming.
The five failures we see most
Muted metadata text below 4.5:1
Dates, breadcrumbs, table-of-contents links, card descriptions and “last updated” lines. They are small, grey, and usually set once early in a design and never measured. Sample every muted token against every background it lands on: page, sidebar and callout tints are all different.
Code blocks that cannot be scrolled by keyboard
A block with overflow-x: auto and no tabindex is scrollable by mouse and trackpad only. Add tabindex="0" plus role="region" and an accessible name so it is reachable, announced, and scrollable with the arrow keys.
Skipped heading levels
Usually caused by picking headings for size rather than structure: an h4 because h3 looked too large. Fix it in CSS, not in the markup. Documentation is navigated by heading more than almost any other kind of site, so this one costs more here than elsewhere.
Mobile navigation that traps focus
A drawer that opens over the page but leaves focus behind it means a keyboard user tabs through an invisible menu. Move focus in on open, hold it inside while open, restore it to the trigger on close, and make sure Esc dismisses it.
Icon-only buttons with no accessible name
Copy buttons, theme toggles, search triggers and close buttons. If the content is a glyph, an icon font or an SVG, the control announces as “button” and nothing else. Add an aria-label, and hide the decorative glyph with aria-hidden="true".
How to test
| Method | Catches | Time |
|---|---|---|
| axe DevTools or WAVE | Contrast, missing alt, ARIA misuse, label gaps | Minutes per page |
| Keyboard-only pass | Traps, invisible focus, unreachable controls | 10 minutes per template |
| Zoom to 200% and 320px width | Reflow and clipping failures | 5 minutes |
| Screen reader (NVDA or VoiceOver) | Heading outline, link text, control naming | 30 minutes |
| Lighthouse accessibility audit | A rough regression signal in CI | Automatic |
Test one page of each template rather than every page, since a documentation site has perhaps five distinct layouts, and the content pages differ only in prose.
What automated tools cannot catch
Automated checkers find somewhere around a third of real issues. They cannot tell you whether your alt text is useful, whether headings describe their sections, whether focus order matches the visual layout, or whether an error message explains how to fix the problem.
So a clean axe report is a starting line, not a finish. The keyboard pass is the highest-value fifteen minutes in this entire list, and it needs no tooling at all.
If you publish an accessibility statement, it should describe what you actually tested and what you know is outstanding. A statement claiming full AA conformance on the strength of a Lighthouse score is worse than no statement, because it tells disabled users they can rely on something nobody verified.
Where to start
Run the keyboard pass on one page today. It takes ten minutes, needs nothing installed, and will find more than your first automated scan does. Then measure your muted text colours, because that is where the rest of the failures are hiding.
Doku treats these as build constraints rather than a later audit: semantic landmarks, a skip link, ARIA labelling on every icon control, visible focus states, and light and dark colour tokens chosen for contrast. See Accessibility for the specifics.