Screen reader announces nothing when focus reaches p5.js canvas — missing tabindex and ARIA on the generated element
0 reputation · 03 Mar 2020, 10:55 UTC
0 reputation · 03 Mar 2020, 10:55 UTC
A p5.js sketch renders correctly in the browser, but when navigating the page with a keyboard and a screen reader (NVDA or VoiceOver), the canvas produced by createCanvas() is skipped entirely. It receives no focus and no accessible name is announced, so assistive technology users have no indication that interactive content exists on the page.
Inspecting the generated <canvas> element in DevTools shows it has no tabindex, no role, and no aria-label by default. Manually adding tabindex='0' and an ARIA role to the canvas element is a possible workaround, but there is concern that modifying the element p5.js manages internally could conflict with its mouse and keyboard event handling. The p5.Accessibility add-on is available, though it appears oriented toward text output via live regions rather than exposing the canvas itself. Assume p5.js 1.x, current stable release.
The default createCanvas() element is not focusable and has no accessible name, so screen readers skip it. This is not an intentional accessibility feature; it is a known gap that you can fix without interfering with p5.js’s internal mouse or keyboard handling.
p5.js treats the canvas as a pure graphics surface and relies on mouse/touch events. It therefore does not add tabindex, role, or aria-label by default.
tabindex='0' (or -1 for script‑only focus) and an aria-label or aria-labelledby does not stop p5.js from forwarding mouse and key events.createCanvas(), obtain the canvas element, e.g., const cnv = document.querySelector('canvas');tabindex='0' so it can receive keyboard focus via Tab.cnv.setAttribute('aria-label', 'My p5 sketch');.keyPressed() still fires.If you prefer not to modify the canvas directly, wrap it in a focusable div:
<div tabindex='0' role='application' aria-label='p5 sketch'>
<!-- p5.js will draw into the inner canvas -->
</div>
The container receives focus and the label; the inner canvas remains unchanged and continues to receive p5.js events.
Do you need the canvas itself to receive keyboard focus for interaction (e.g., drawing with keys), or is announcing its presence sufficient? This determines whether you should use tabindex='0' (focusable) or tabindex='-1' (script‑only) and whether a wrapper with role='application' is appropriate.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.