accessibility
Expanded state
also called aria-expanded (aria), disclosure state (aria-apg), open state (community)
The open or closed state of a disclosure, exposed with aria-expanded on the control that owns it rather than on the panel it reveals.
aria-expanded goes on the control, never on the thing it reveals. The APG puts it plainly
for the disclosure pattern: when the content is visible the element with role button has
aria-expanded set to true, and when the content is hidden it is set to false. That is the
whole attribute, and the placement is the part people get wrong. A screen reader announces
state as part of the control it is on, so a reader arriving at a button hears “Shipping
details, button, collapsed” and knows what pressing it will do. Put the attribute on the
panel instead and the button announces nothing, because a control that says nothing about its
own state is a control you have to press to understand.
Absence is meaningful too. MDN is explicit that the presence of the attribute indicates
control, so it should not be added to elements that do not own an expandable region. A button
with no aria-expanded is a button that does something; a button with aria-expanded="false"
is a button that will show you something. That distinction is worth protecting, which is why
scattering the attribute across every button in a toolbar is worse than leaving it off.
Several patterns carry it and they are not interchangeable.
A disclosure and an accordion header use it for content that
appears in the flow. A menu button uses it alongside
aria-haspopup, which says what kind of surface will appear while
aria-expanded says whether it is there right now; the two answer different questions and a
menu button wants both. A combobox carries it on the input for its popup. A
tooltip or a toggletip does not, and neither does a
modal dialog trigger, since a dialog is not a region that control keeps
expanded. Whatever the pattern, the state has to be written when the state actually changes:
an attribute set once at build time and never updated is a lie the reader has no way to
check, and wiring the control to its region with aria-controls does not rescue it. The
control’s accessible name should hold still across the flip for the same
reason: with the state already announced, a button that renames itself from Show to Hide is
saying the same thing twice and disagreeing with itself half the time.
The visual half of the same message is the part everyone remembers to build. A rotating
disclosure triangle, an icon morph from plus to minus,
a chevron that flips: all of these are the sighted spelling of exactly what aria-expanded
carries, which makes them a useful check on each other. If the glyph changes and the
attribute does not, the two halves of the interface disagree, and only one of them is being
read aloud.
Which word?
| If you want | say |
|---|---|
| the trigger must say whether its panel is open | expanded state |
| a button opens a menu and gives no warning | has popup |
Related
See also: Disclosure · Disclosure triangle