ARIA state
aria-expanded
Whether the thing this control opens is currently open.
It is the difference between a button that announces as collapsed and the same button announcing as expanded. Flip it when the panel opens, flip it back when the panel closes. The opening is your code's work. Saying so is this attribute's.
Which roles may carry aria-expanded
- Value
- true/false/undefined
- Filed as
- A state, which is how ARIA files it and not a rule about how often it changes.
- Roles that may carry it
application,button,checkbox,combobox,gridcell,link,listbox,menuitem,row,rowheader,tab,treeitem- Roles that inherit it
columnheader,menuitemcheckbox,menuitemradio,rowheader,switch
Those lists are not advice. Browsers are required to ignore a non-global attribute sitting on a role that does not support it, so aria-expanded on the wrong element is not weak, it is absent. You can read it in the DOM and nobody using a screen reader can.
Every role above comes from the specification's own list for this attribute, checked name for name. The normative definition stays with the W3C, in the aria-expanded section of the ARIA specification.
Keeping aria-expanded true
A menu button stuck on false is the most common lie in ARIA, and it is written the same way every time. The attribute goes in at build time, the menu opens, and the markup goes on insisting it is shut. Leaving it off entirely is a different outcome and not always the safer one. The default is undefined, meaning the element is neither expandable nor collapsible, but on a combobox the implicit value is false, meaning collapsible and currently closed. So the same absent attribute means two different things depending on what it is sitting on. Set it inside the function that does the opening, never in the one that renders the page.
How aria-expanded gets checked
There are test rules that check an ARIA attribute is one that exists, is allowed on the role underneath it, and carries a value of the right type. What they map to is ARIA's own author requirements rather than any WCAG criterion, so a misplaced attribute breaks ARIA without being a WCAG failure by itself. It becomes one under 4.1.2 Name, Role, Value the moment the missing or wrong value means the control's state cannot be worked out programmatically, which is what usually happens next.
Nothing automated catches the failure this page is about. A stale value is a valid value, on a permitted role, with the right type. It is only wrong about the world.
Attributes you will meet alongside aria-expanded
- aria-activedescendant Points at the item inside a composite widget that is currently active, when focus stays on the container.
- aria-autocomplete How a text field predicts what you are typing.
- aria-checked Whether a checkbox, radio or switch is on, off, or partly on.
- aria-colindex Which column a cell is in, counting from the real table rather than what is shown.
- aria-disabled Says a control is present but not available. Unlike the disabled attribute, it stays focusable, so people can still find out it is there.
- aria-errormessage Points at the message explaining why this field is invalid. Only meaningful while aria-invalid is set.
- aria-haspopup Says this control opens something, and what kind of thing it opens. A menu, a dialog, a listbox.
- aria-invalid Says a field's value has failed validation.
Every ARIA state and property · Every ARIA role · ARIA explained