The accordion is quietly one of the most reused components on the entire web. FAQ pages, filter panels, settings screens, mobile navigation menus, almost every substantial site has one somewhere. It is also, quietly, one of the most commonly broken components for assistive technology, and the reason is nearly always the same three-line shortcut: a <div> with an onClick handler standing in for what should be a real, semantic, stateful button.
A sighted mouse user cannot tell the difference between a properly built accordion header and a div-with-a-click-handler one. Both look identical, both respond to a click, both expand and collapse the section underneath. A screen reader user hits a completely different experience with each: a real button announces itself as a button, announces whether the section it controls is currently expanded or collapsed, and responds to Enter or Space the same way any other button on the page does. A div with a click handler announces as plain, unstateful text, with no indication it is interactive at all, no indication of its current state, and, unless someone specifically added tabindex and keyboard event handling by hand, no way to activate it with a keyboard at all.
The Stat: WCAG Success Criterion 4.1.2 Name, Role, Value, a Level A requirement, is violated by any accordion built from a plain div with a click handler instead of a real button with aria-expanded, because a screen reader has no way to announce whether the section is open or closed. (Source: W3C WCAG 2.1, Success Criterion 4.1.2)
Why the Shortcut Happens So Often
Nobody sets out to build an inaccessible accordion. The shortcut almost always happens for a mundane, practical reason: a <button> element carries default browser styling, a border, a background, a focus outline, that needs to be reset to match a design system's visual language, and it is genuinely faster in the moment to reach for a plain <div> with no default styling to fight against, add a click handler, and move on. The cost of that shortcut is invisible to whoever wrote it, because they tested it the way almost everyone tests a UI component during development: with a mouse, looking at the screen.
What a Real Accordion Header Needs, Specifically
The fix is not complicated, and it does not require abandoning custom styling. A <button> element, styled however the design calls for (all of its default browser styling can be reset with two or three CSS rules), with aria-expanded="true" or aria-expanded="false" reflecting its current state, and aria-controls pointing at the id of the content region it toggles. That is the entire structural requirement. The button's visual appearance is completely independent of these three things; a properly accessible accordion header can look exactly like the div-based version it replaces, pixel for pixel.
Keyboard behavior follows automatically once a real <button> is used: Tab reaches it in the natural document order, and both Enter and Space activate it by default, without any custom key-handling code needing to be written at all. This is one of the more direct, low-effort wins available in accessibility work generally: using the native element the browser already provides, rather than reconstructing its behavior from scratch, gets a meaningful share of the correct behavior for free.
What Gets Announced, Before and After
With the div-based version, a screen reader user tabbing through the page (if they can even reach it, since a div with no tabindex is not keyboard-focusable at all by default) hears only the visible label text, with no indication it is interactive, clickable, or connected to any other content on the page. With the button-based fix, the same element announces as "FAQ question one, button, collapsed" and, once activated, "FAQ question one, button, expanded," giving a screen reader user the exact same state information a sighted user gets for free by looking at a rotated chevron icon.
A Common Half-Fix Worth Naming Separately
There is a specific middle-ground pattern worth calling out because it is common and easy to mistake for a real fix: adding role="button" and tabindex="0" to the existing div, without also adding aria-expanded or real keyboard event handling for Enter and Space. This makes the element announce as a button and become reachable by Tab, which feels like meaningful progress, and it is a genuine improvement over a completely unlabeled div. It still leaves two real gaps: without aria-expanded, a screen reader user still cannot tell whether the section is currently open or closed, only that a button exists; and without explicit keydown handling for Enter and Space, a role="button" div does not automatically respond to those keys the way a native <button> does, unlike the automatic native behavior a real button element provides for free. This half-fix pattern shows up often precisely because it addresses the most visible symptom, an inability to Tab to the element at all, while leaving the state-announcement and full-keyboard-activation gaps that a native button would have closed automatically, without any extra code, in the first place.
A Note on Multi-Panel Accordions and Single-Open Behavior
One more detail worth getting right: whether the accordion allows multiple panels open at once or forces only one panel open at a time (closing the previous one automatically when a new header is activated) is a design decision, not an accessibility requirement either way, but whichever behavior is chosen needs to be reflected accurately and consistently in the aria-expanded state of every header, not just the one most recently interacted with. A single-open accordion that visually closes the previous panel but fails to update that panel's aria-expanded back to false leaves a screen reader with an inaccurate picture of the interface, reporting a section as open that has actually been visually collapsed, a subtle desync bug that is easy to introduce when panel-closing logic is handled separately from the ARIA state update that should accompany it.
Where This Shows Up Beyond FAQ Pages
Accordions are not confined to FAQ pages. The same pattern underlies collapsible filter panels on ecommerce category pages, expandable settings sections, and mobile navigation menus built as a stack of collapsible groups. Every one of these inherits the identical failure if built the same way, and every one of these gets the identical fix. This is one of several custom interactive patterns worth auditing as a group rather than one at a time; our keyboard navigation guide for custom components covers the general discipline that applies across all of them, and our guide to when ARIA helps and when it actively hurts is directly relevant here too, since the correct fix for an accordion is a real native button plus two ARIA attributes, not a heavier ARIA-only reconstruction of button semantics that a native element already provides for free.
If your site has accordions that have never specifically been checked this way, five minutes with a keyboard and no mouse will surface the problem immediately if it exists. Our free accessibility tools can catch many of these structural gaps automatically, and our team is reachable directly at experts@wcag.world if you want a closer look at a specific component. The W3C's Accordion design pattern and its Name, Role, Value guidance are both worth reading directly for the complete technical requirement.
