Skip to main content

Search rules

Search all UI Guides rules by name, category, or source

contentWeb Platform

Canvas and WebGL Need an Accessible Fallback

MUST

MUST: A <canvas> (2D or WebGL) is an opaque bitmap to assistive tech. Name it (role="img" + aria-label stating the data, or descriptive fallback children between the tags), mirror any interactive 3D objects in real focusable DOM with an announcer, and provide the same information without the canvas (a data table, a static-image fallback where WebGL is absent).

A <canvas> renders pixels the accessibility tree cannot see — give it a name, fallback content, and a non-canvas path to the same information

<canvas role="img" aria-label="Revenue by quarter: Q1 $12k, Q2 $18k, Q3 $15k, Q4 $24k" />
{/* plus a visually-hidden <table> with the same data */}

Bad

Good

Why it matters

Distilled from the Poimandres react-three-a11y docs and the MDN canvas-accessibility guidance, and it is the hardest surface content-accessible-content and content-icons-have-labels ever point at. A `<canvas>` — 2D or WebGL — is a single flat bitmap to a screen reader: every bar in the chart, every clickable region, every label you painted is invisible and unreachable, because none of it is in the DOM.

Three fixes stack, in order of effort. First, name the surface: a static visualisation takes `role="img"` plus an `aria-label` that states what it shows ("Revenue by quarter: Q1 $12k, Q2 $18k…"), and any markup placed BETWEEN the `<canvas>` tags is both the legacy no-canvas fallback and what AT reads. Second, for anything interactive, mirror it in real focusable DOM — WebGL objects cannot take Tab focus or receive key events, which is exactly why react-three-a11y injects a parallel HTML layer and an announcer node beside the R3F canvas.

Third, provide the information without the canvas at all: a data table behind the chart, and a static image where WebGL is unavailable (the progressive-enhancement half — see performance-webgl-gpu-budget for the runtime side). The test is the corpus's standard one: turn the visual off and check the accessibility tree still answers what the picture said.

Built by Gleb Stroganov, design engineer at Evil Martians.

The rules come from other people's skills and guidelines — Vercel, Rauno Freiberg, @Ibelick, impeccable, Emil Kowalski, Tailwind, RAMS — each one credited on the Sources page. The work here is extraction and wiring: every rule is pulled into one corpus, given a good and a bad example you can operate, a MUST/SHOULD/NEVER rule an agent can paste, and a link back to where it came from.