Glossary
/
aria-expanded

aria-expanded

What is aria-expanded?

The aria-expanded attribute is part of WAI-ARIA, the Web Accessibility Initiative's Accessible Rich Internet Applications spec. It's set on an interactive, focusable element to tell assistive technologies whether a grouping element it owns or controls, such as a menu, accordion panel, tree, or dialog, is currently expanded or collapsed. Screen reader users rely on this value to know the current state of a control before they activate it.

At a glance

Category Detail
Type ARIA attribute (state)
Related standard WAI-ARIA 1.2
Values true, false, undefined (default)
Related terms WAI-ARIA, ARIA attributes, ARIA roles

Why is aria-expanded important when it comes to accessibility?

Sighted users get a lot of visual feedback on a page that provides context. A chevron icon rotates, an accordion panel slides open, or a background color shifts – all of it signals that a toggle just changed state. None of that styling reaches a screen reader on its own. Without aria-expanded, a button element that opens a dropdown menu or an accordion header that reveals a panel announces as a plain, static control, with no indication of whether it's currently expanded or collapsed.

aria-expanded gives assistive technology users the same state feedback sighted users already get for free, so a screen reader can announce something like "Filters, button, collapsed" before the user even presses it, and "Filters, button, expanded" the moment they do. It’s most important for expandable and collapsible regions: accordions, navigation menus, filter panels, and tree views, where the interactive elements controlling visibility don't always look any different once they're toggled. Missing or stale aria-expanded values are a common finding during an accessibility audit of custom navigation and accordion components.

Sighted keyboard users don’t hear aria-expanded, but they can still benefit from it. When the visual indicator, such as a rotating chevron, is styled from the attribute itself, what they see and what a screen reader announces can’t drift apart.

How does aria-expanded work?

aria-expanded takes one of two explicit values, or is left off entirely:

  • true – The grouping element this element owns or controls is expanded.
  • false – The grouping element this element owns or controls is collapsed.
  • undefined (default) – The element doesn’t own or control an expandable grouping element.

Most elements should simply omit the attribute rather than set it to false, since false implies the element is a toggle that happens to be closed, while omitting it says the element isn't a toggle in the first place. A handful of roles, such as combobox, default to false instead, since a combobox is always expandable by definition.

The attribute belongs on the interactive control, not the content it reveals. Common examples include:

  • A button element that expands a panel
  • A menuitem whose child menu is currently hidden
  • A tab that reveals extra content
  • A parent treeitem or row elements in a tree or grid that can be expanded to show child nodes

End nodes with no children shouldn't carry aria-expanded at all, since doing so would incorrectly describe them as parent nodes to assistive technology.

Beyond button, aria-expanded is supported directly on application, checkbox, combobox, gridcell, link, listbox, menuitem, row, rowheader, tab, and treeitem, and it’s inherited by columnheader, menuitemcheckbox, menuitemradio, and switch. Most follow the same pattern: an interactive element controls the visibility of other content, and aria-expanded reports whether that content is currently shown.

On its own, aria-expanded only identifies the control. To tell assistive technology which grouping container it affects, pair it with the aria-controls attribute, pointing to the id of the element it reveals. aria-owns is the alternative when the container should be treated as the control’s child but sits elsewhere in the DOM, though aria-controls is far more common in practice.

None of this happens automatically. aria-expanded has no native browser behavior – unlike the HTML <details> element, there's no built-in toggle logic. The value has to be updated via JavaScript every time the user changes the control's state, kept in sync with whatever actually shows or hides the grouping element – the hidden attribute, a CSS display change, a class toggle, or some other in-page change to the element's visibility. If the two fall out of sync, a sighted user sees one thing while a screen reader announces another.

In practice, most of these follow the same underlying pattern: an interactive element controls the visibility of other elements, and aria-expanded reports whether that's currently happening.

aria-expanded doesn’t affect layout, visibility, or styling by itself – it’s purely a state communicated to assistive technologies, though CSS can target it with an attribute selector.

aria-expanded example

A collapsible navigation menu is a typical use case. The trigger carries aria-expanded and aria-controls; the menu itself starts hidden:‍

<button aria-expanded="false" aria-controls="nav-menu">
  Menu
</button>
<ul id="nav-menu" hidden>
  <li><a href="/pricing">Pricing</a></li>
  <li><a href="/features">Features</a></li>
</ul>
const button = document.querySelector('[aria-controls="nav-menu"]');
const menu = document.getElementById("nav-menu");

button.addEventListener("click", () => {
  const isExpanded = button.getAttribute("aria-expanded") === "true";
  button.setAttribute("aria-expanded", String(!isExpanded));
  menu.hidden = isExpanded;
});

‍When the button is activated, the script flips aria-expanded between true and false and removes or restores the hidden attribute on the menu in the same step. A screen reader announces something like "Menu, button, collapsed" before the click and "Menu, button, expanded" immediately after, matching what a sighted user sees on screen.

An accordion header follows the same logic, just with a content panel instead of a menu:‍‍

<h3>
  <button aria-expanded="true" aria-controls="panel-1">
    Shipping details
  </button>
</h3>
<div id="panel-1">
  <p>Orders ship within two business days.</p>
</div>

Here, aria-expanded="true" and the visible panel agree, so a screen reader user and a sighted user both understand the section is currently open.

aria-expanded vs. aria-haspopup

aria-expanded is easy to confuse with aria-haspopup, as both often sit on the same button element. They cover different information.

aria-expanded aria-haspopup
What it tells assistive technology The current state of a grouping element the control owns or controls Whether an element triggers a popup at all, and what type
When it changes Dynamic – updates every time the control is toggled Static – set once and doesn't change as the popup opens or closes
Values true, false, or omitted entirely false (default), true, menu, listbox, tree, grid, dialog

A menu button commonly sets both: aria-haspopup="menu" tells assistive technology users what kind of popup to expect, and aria-expanded, starting at false, tells them whether that popup is currently open. Leave aria-expanded off a popup trigger, and the popup type is still announced correctly, but a screen reader user has no way to tell whether it's already open without navigating into it.

Common mistakes or misconceptions

  • Forgetting to update the value. Toggling a menu or panel with CSS or the hidden attribute, but never updating aria-expanded in the same script, leaves assistive technology users with a stale state – this is the most common reason aria-expanded isn't working as expected.
  • Setting it on elements that don’t toggle anything. Adding aria-expanded – even with a value of false – to a button or link that doesn’t own or control an expandable grouping element misrepresents it as a closed toggle. Leave the attribute off entirely.
  • Confusing aria-expanded with the hidden attribute. aria-expanded only communicates state to assistive technology. It doesn’t hide or show anything by itself – the hidden attribute or a CSS display change is still needed to actually toggle the content.
  • Adding it to leaf nodes in a tree or grid. Only parent items with children should carry it.

Frequently Asked Questions

Can you style an element based on aria-expanded with CSS?

Yes. An attribute selector like [aria-expanded="true"] lets you target a control's styling based on its current value, commonly used to rotate an icon or change a background when a menu or panel opens. The attribute itself has no visual effect; the CSS rule is what produces the change.

Does aria-expanded need JavaScript to work?

Yes. Browsers don’t change the value automatically, so a script has to set it whenever the controlled content opens or closes – otherwise it stays at whatever was written into the markup.

‍

For simple show/hide content, the native <details> and <summary> elements handle the expanded state without any JavaScript.

Why isn't aria-expanded working with my screen reader?

In most cases, the value isn’t being updated when the control’s state changes, so assistive technology announces whatever was set when the page loaded rather than the current state.

‍

Check that the toggle script sets aria-expanded on every interaction, and confirm with a browser’s accessibility tree inspector that the value actually flips between true and false.

‍

Two other common causes: the attribute sits on the revealed content instead of the control, or it’s on an element without a supporting role, such as a plain <div>, which browsers are required to ignore.

‍

Try our website monitor free

Automate website monitoring tasks
and keep your pages compliant