Standards · ARIA

State Widget state

aria-expanded

Indicates whether a collapsible element — disclosure button, combobox, menu, treeitem — is currently open. Takes "true" or "false". Typically paired with aria-controls pointing at the region the control opens.

When to use

On any control that opens and closes another region of the UI: an accordion header, a “show more” disclosure button, a combobox trigger, a menu button, a treeitem with children, a hamburger nav toggle. The control stays the same element across both states — only the attribute flips.

If the control toggles state on the element itself (mute / unmute, follow / unfollow), use aria-pressed instead. aria-expanded describes a relationship with another region, usually identified by aria-controls.

The role determines whether aria-expanded is meaningful: it is supported on button, combobox, link, tab, treeitem, menuitem, gridcell, row, and a few others. Putting it on a <div> with no role does nothing useful.

How to keep it in sync

Valid values are "true" (region is open) and "false" (region is closed). The default if omitted is “no expanded state at all” — which is different from "false". If your control is ever expandable, render aria-expanded="false" in the closed state rather than leaving it off.

Update the attribute in the same code path that animates the region open or closed. The attribute is the source of truth that screen readers read; the visual chevron is a secondary cue for sighted users.

Pair with aria-controls="<region-id>" so the screen reader can announce the relationship: “Filters, button, collapsed, controls filter-panel”. Some assistive technologies offer a shortcut to jump to the controlled region.

Common failures

  • Toggling a CSS class on the panel but forgetting to flip aria-expanded.
  • Using aria-expanded on a non-interactive element with no role. The attribute is ignored.
  • Adding aria-expanded="true" only — never rendering the "false" state. Screen readers announce nothing in the closed state.
  • Using aria-expanded on a control that doesn’t actually expand a region (a “Submit” button).
  • Confusing aria-expanded with aria-pressed on toggle buttons that don’t open a separate region.
  • Omitting aria-controls, leaving the relationship between trigger and panel implicit.

Example

<button
  type="button"
  aria-expanded="false"
  aria-controls="filters-panel"
  onclick="toggle(this)"
>
  Filters
</button>

<div id="filters-panel" hidden>
  <!-- filter controls -->
</div>