WCAG requirements for charts, criterion by criterion
Which of the 55 WCAG 2.2 A/AA success criteria actually bite for a chart — what each means in practice, and how to check it.
Most WCAG criteria are page-level and land on the embedding application. But a chart is an interactive, graphical, data-dense component, so an unusually large slice of the standard applies inside the component boundary. These are the ones that decide whether your data views pass an audit.
The load-bearing criteria
| Criterion | What it means for a chart | How to verify |
|---|---|---|
| 1.1.1 Non-text Content (A) | The rendered graphic needs a text alternative that carries the data, not a caption. A one-line label is not an alternative for a thousand points; a structured data table + a summary sentence is. | Turn the screen reader on: can you get actual values without seeing pixels? |
| 1.3.1 Info & Relationships (A) | Series/point structure must exist programmatically — table headers scoped, legend entries related to series, not just visually adjacent text. | Inspect the accessibility tree; check the table has real <th> headers. |
| 1.4.1 Use of Color (A) | Series can't be distinguishable by hue alone — dash patterns, markers, or direct labels are the second channel ("double encoding"). | Grayscale the chart: can you still tell series apart? |
| 1.4.3 / 1.4.11 Contrast (AA) | 1.4.3 covers text (ticks, labels: ≥4.5:1). 1.4.11 covers the marks themselves — lines, bars, focus indicators need ≥3:1 against the background. Canvas pixels are not exempt. | Compute ratios for the actual rendered colors on the actual background. |
| 1.4.4 / 1.4.10 Resize & Reflow (AA) | 200% zoom and 320px-wide viewports must not clip or overlap — tick labels thin out, legends wrap, containers stay fluid. | Zoom to 200%; resize to 320px; look for loss of content or function. |
| 2.1.1 / 2.1.2 Keyboard (A) | Everything pointer does needs a keyboard path: move between data points, switch
series, zoom (+/- for wheel), pan — and focus must never
get trapped inside the chart. |
Unplug the mouse. Reach every value, then Tab out cleanly. |
| 2.4.7 Focus Visible (AA) | The focused chart surface (and every control) shows a visible ring. | Tab through; the focus position must always be visually obvious. |
| 2.5.7 Dragging Movements (AA) | Drag-to-pan needs a single-pointer alternative (pager buttons, click-to-step). | Pan the chart without ever dragging. |
| 2.5.8 Target Size (AA) | Legend toggles, pagers, export buttons: ≥24×24 CSS px (or spacing equivalent). | Measure the interactive targets. |
| 4.1.2 Name, Role, Value (A) | The chart surface has an accessible name and role; legend toggles expose pressed state; the focused point's value is programmatically determinable. | Read the accessibility tree, not the DOM. |
| 4.1.3 Status Messages (AA) | Value announcements as the cursor moves must flow through a live region — without stealing focus, and debounced so key-repeat doesn't flood the reader. | Hold an arrow key with a screen reader running; listen. |
| 3.1.2 Language of Parts (AA) | If the page is German, the chart's own UI prose (keyboard help, summary, captions) should be German too — untagged English passages fail. | Localize the chart's fixed strings alongside your app. |
From criteria to paperwork: VPAT, ACR, EN 301 549, Section 508
Procurement doesn't ask "is it accessible" — it asks for an ACR (Accessibility Conformance Report, written on the ITI VPAT® template) stating per-criterion conformance: Supports / Partially Supports / Does Not Support / Not Applicable. The same WCAG substance is referenced by EN 301 549 in the EU (the standard behind the European Accessibility Act) and Section 508 for US federal buyers — one evidence base, three editions of the report.
Two things make a chart-layer ACR credible: scoping honesty (the chart component
answers for itself; page-level criteria belong to the host app) and evidence freshness
(a report generated from checks that run on every commit beats a PDF written once a
year). fcharts generates its ACR — all three editions, Markdown/HTML/JSON — from the
committed audit on every build; here's the live sample,
and fcharts-audit --compare diffs two of them so a buyer sees exactly what
changed between versions.