Introduction to aria-expanded
aria-expanded tells assistive technology whether a control’s content is shown or hidden. This guide covers the WAI-ARIA 1.2 values (true, false, and the default undefined), the disclosure and accordion patterns, JavaScript wiring, and the mistakes that leave screen reader users guessing.
aria-expanded At A Glance
- true / false: useful values: expanded vs collapsed; omit the attribute when nothing expands (default undefined) (Source: WAI-ARIA 1.2)
- Jun 6, 2023: WAI-ARIA 1.2 became a W3C Recommendation (current aria-expanded definition) (Source: W3C WAI-ARIA 1.2)
- 4.1.2: WCAG Name, Role, Value requires changeable states like expanded/collapsed to be exposed (Source: W3C Understanding 4.1.2)
- Rule 1: Prefer native details and summary before adding aria-expanded yourself (Source: First Rule of ARIA)
Choose Your Next Step
Learning aria-expanded for a ticket, or ready to have every accordion and menu checked? Start with a free scan, train your team, or talk it through before you spend anything.
Scan A Page First (Free tool)
Best for: a quick first look at common WCAG issues
Run a free one-page scan on AccessibilityScore.in (powered by axe-core). It is a starting point that complements a manual audit; scanners miss stale aria-expanded state and focus traps.
Run a free accessibility scan (opens in a new tab)
Train On ARIA And Focus
Best for: developers shipping disclosures and accordions
Workshops cover ARIA states, keyboard behaviour and focus management so expand/collapse widgets stay usable with NVDA, JAWS and VoiceOver.
Free 30-Minute Call
Best for: first conversations, where you stand, and getting a quote
Tell us which widgets worry you. We explain where you stand and whether a $500 Quick Audit or training fits before you spend on a larger engagement.
Book a Free 30-Min Call (opens in a new tab)
$100 Technical Hour
Best for: teams that need technical answers now
A hands-on session for walking through audit findings, talking with your developer, or reviewing live accordion and menu issues together.
What is aria-expanded?
The aria-expanded attribute tells assistive technology whether the content a control owns or controls is currently shown or hidden. It is defined in the WAI-ARIA 1.2 specification and documented in MDN’s aria-expanded reference. It takes two useful values:
true: the controlled content is currently visible (expanded).false: the controlled content is currently hidden (collapsed).
If a control does not expand anything, leave the attribute off entirely rather than setting it to false; a value of false tells users there is hidden content they can open. Leaving it off gives the specification’s default value, undefined, which means the element does not control anything expandable. There is no aria-collapsed attribute: a collapsed control is simply aria-expanded="false".
It’s important to note that aria-expanded goes on the element that controls the expansion, usually a button, not on the content itself. Screen readers then announce something like “Shipping details, button, collapsed”, and “expanded” once it is opened.
Why is aria-expanded Important?
For screen reader users, the visual change when a panel opens is not communicated on its own. Without aria-expanded, a user presses a button and hears nothing, so they cannot tell whether anything happened or whether content appeared further down the page. The attribute is also how a component meets WCAG 4.1.2 Name, Role, Value, which requires states that users can change to be exposed to assistive technology (see W3C’s Understanding 4.1.2).
Start With Native HTML: details and summary
The W3C’s first rule of ARIA is to use a native element when one exists. For a simple show/hide section, HTML already has one:
<details> <summary>Shipping details</summary> <p>Orders ship within two business days.</p> </details>
Browsers expose the expanded or collapsed state of <summary> automatically, and it works with the keyboard without any JavaScript. Use aria-expanded when you need a custom design or behaviour that <details> cannot provide.
The Disclosure Pattern
A disclosure is the simplest pattern that uses aria-expanded: one button that shows and hides one section of content. The APG Disclosure pattern describes it, and WebAIM’s article on accessible disclosures is a practical companion.
<button type="button" aria-expanded="false" aria-controls="ship-info">Shipping details</button> <div id="ship-info" hidden> <p>Orders ship within two business days.</p> </div>
Using a real <button> gives you focus, Enter and Space activation and the button role for free. The hidden attribute removes the collapsed content from both the screen and the accessibility tree. In this pattern the APG lists aria-controls as optional, while the WAI-ARIA 1.2 definition of aria-expanded says authors should add it whenever the expandable content is not owned by the button, so including it is a safe default. Screen reader support for aria-controls is limited, though, so it should never be the only thing that connects the button and the content. Place the content directly after the button in the DOM so users find it by reading on.
Practical Examples of aria-expanded
Example 1: Accordion
An accordion is a stack of disclosures, each with a heading. The APG Accordion pattern puts each button inside a heading, so screen reader users can jump between sections with heading navigation:
<h3> <button type="button" id="acc1-btn" aria-expanded="true" aria-controls="acc1-panel">Section 1</button> </h3> <div id="acc1-panel" role="region" aria-labelledby="acc1-btn"> Content of Section 1 </div> <h3> <button type="button" id="acc2-btn" aria-expanded="false" aria-controls="acc2-panel">Section 2</button> </h3> <div id="acc2-panel" role="region" aria-labelledby="acc2-btn" hidden> Content of Section 2 </div>
In the accordion pattern the APG does expect aria-controls on each header button. The role="region" with aria-labelledby is optional; it turns each panel into a named landmark, which helps when panels are long, but the APG advises against it when more than about six panels can be open at the same time, because too many landmarks become noise. The heading level should fit the page outline. The aria-labelledby guide explains how that naming works.
Example 2: Site Navigation With Dropdowns (Disclosure Navigation)
Most “menus” on websites are lists of links that open from a button. They should use the disclosure pattern, not the WAI-ARIA menu or menubar roles. Those roles are for application-style menus like a desktop app’s File menu: they change how screen readers handle keys and require arrow-key support. The APG’s disclosure navigation example shows the recommended approach for website navigation:
<nav aria-label="Main">
<ul>
<li>
<button type="button" aria-expanded="false" aria-controls="services-sub">Services</button>
<ul id="services-sub" hidden>
<li><a href="/service/accessibility-audit-services/">Audits</a></li>
<li><a href="/service/accessibility-training-workshops/">Training</a></li>
</ul>
</li>
<li><a href="/contact/">Contact</a></li>
</ul>
</nav>
Users Tab to “Services”, press Enter or Space to open it, and Tab through the links as normal. Pressing Escape to close the submenu and return focus to its button is a helpful addition.
Example 3: Other Places aria-expanded Appears
You will also see aria-expanded on a combobox, to say whether its list of options is showing, and on a button that opens a real application menu (with aria-haspopup). In those widgets it is one part of a larger pattern, so follow the matching APG pattern rather than adding the attribute on its own.
JavaScript Integration
To make aria-expanded dynamic, update it in the same function that shows or hides the content, so the two can never drift apart:
document.querySelectorAll('button[aria-expanded]').forEach((button) => {
const panel = document.getElementById(button.getAttribute('aria-controls'));
button.addEventListener('click', () => {
const isExpanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!isExpanded));
panel.hidden = isExpanded;
});
});
This script toggles the attribute and the panel’s hidden property together. Because it uses <button> elements, the click event also fires on Enter and Space, so keyboard users get the same behaviour. If your design needs animation, you can drive the CSS from the attribute itself, for example button[aria-expanded="true"] + .panel, so the state on screen always follows the state screen readers hear:
button[aria-expanded="true"] .chevron {
transform: rotate(180deg);
}
button[aria-expanded="false"] + .panel {
display: none;
}
Styling from the attribute means a rotated arrow can never contradict what a screen reader announces. For component frameworks, our accessible React development team applies the same rule: render the attribute from component state.
Common aria-expanded Mistakes
| Mistake | What goes wrong |
|---|---|
| Stale state | The panel opens but the attribute still says false (CSS class toggled without updating ARIA, or a “close all” script skips the button). Screen reader users hear the opposite of the truth. |
| Attribute on the panel | aria-expanded belongs on the control. On a div panel it is ignored or misleading. |
| Non-interactive control | A clickable div or span with aria-expanded is not focusable and has no role. Use a real <button>. |
| Misusing menu roles | Adding role="menu" to site navigation without arrow-key support breaks keyboard and screen reader use. Use the disclosure navigation pattern instead. |
| Focusable collapsed content | Hiding with opacity, off-screen positioning or zero height still lets Tab reach invisible links. Use hidden, display: none or the inert attribute. |
| CSS not synced with ARIA | The arrow rotates while the attribute stays the same (or the reverse). Style from the attribute selector so visuals cannot drift. |
| Label fights the state | Switching text between “Show” and “Hide” while toggling aria-expanded can produce “Hide, button, expanded”. Keep a stable label; let the state announce expand/collapse. |
Testing aria-expanded
Check with the keyboard first: Tab to each control, press Enter and Space, and make sure focus never lands inside a collapsed panel. Our manual keyboard testing guide covers the routine. Then use a screen reader to confirm that each control announces “collapsed” or “expanded” correctly before and after activation; see our screen reader testing guide. Your browser’s Accessibility panel in developer tools also shows the current expanded state of a selected element. If you would rather have specialists check every disclosure, accordion and menu on your site, our manual accessibility audit services test them with NVDA, JAWS and VoiceOver, starting with a $500 Quick Audit.
Best Practices for aria-expanded
- Use
<details>and<summary>when a simple native disclosure will do. - Put
aria-expandedon a real<button>that controls the content, never on the content. - Add
aria-controlsin accordions, where the APG expects it, and as a safe default in disclosures; keep the content right after the button either way. - Update the attribute in the same code that shows or hides the content.
- Remove collapsed content from the tab order.
- Use the disclosure pattern for site navigation, not
menuroles. - Make sure everything works with the keyboard, which makes the site more accessible for keyboard and switch users as well as screen reader users.
How aria-expanded Failures Show Up in Accessibility Audits
Broken expand/collapse widgets are one of the most common interactive failures we find in WCAG 2.2 AA audits. They usually fail WCAG Success Criterion 4.1.2 Name, Role, Value because the expanded or collapsed state never reaches assistive technology, and they often fail 2.1.1 Keyboard when the control is a non-focusable div or when focus can still enter a collapsed panel.
In a typical audit pass we check every accordion, disclosure, mega-menu and combobox against the APG Disclosure and Accordion patterns: the control is a real button, aria-expanded flips with the visible state, collapsed content is removed from the tab order, and NVDA, JAWS or VoiceOver announce “collapsed” and “expanded” correctly. Automated scanners catch some missing attributes, but they miss stale state, focus traps and menu-role misuse, which is why a manual pass still matters.
Want a fast first look before booking time with a specialist? Run your URL through AccessibilityScore.in as a starting point; it surfaces many common issues and complements (it does not replace) a manual audit of your interactive components.
Conclusion
aria-expanded is the standard way to expose expand/collapse state. Start with native HTML, follow the APG disclosure and accordion patterns, keep the attribute in sync with what is on screen, and test with a keyboard and a screen reader.
To keep learning, read our ARIA essentials quick-start guide, our overview of ARIA attributes and our guides to aria-label and aria-labelledby.
Related Resources
- Accessibility remediation services
- WCAG 4.1.2 Name, Role, Value guide
- Accessibility training workshops: ARIA and focus management coaching for developers
- ARIA attributes explained
- Manual keyboard testing
- Interactive aria-expanded reference (Developer Playground)
- MDN: aria-expanded
Work With Us
If your accordions, menus and other interactive components need a real accessibility review, start with a $500 Quick Accessibility Audit: automated checks plus manual spot checks of up to 5 templates, with a prioritised top-10 report mapped to WCAG 2.2. For a full review with complete keyboard, NVDA, JAWS and VoiceOver testing, compare audit pricing ($2,000 Complete Audit; Shopify audit $2,000) or see a sample audit report.
Already know the problems? Our accessibility remediation service fixes ARIA and keyboard issues like these directly in your code. Teams that want hands-on ARIA coaching for developers can book our accessibility training workshops.
Not sure where you stand yet? Book a free 30-minute call (Calendly) for a first discussion to understand your site and start a project, or request a free needs assessment; we reply within 2 business days. If you already have audit findings or a developer waiting and need a technical working session (walkthrough, developer Q&A or live issue review), book the $100 one-hour consultation.