aria-expanded-state-mismatch
aria-expanded should match whether the controlled content is shown
Flags an element whose aria-expanded value disagrees with whether the elements its aria-controls names are shown, for manual review.
Applies to. Elements the page shows with aria-expanded="true" or aria-expanded="false" and an aria-controls that names at least one element in the same tree. Left out:
- a combobox, whose
aria-controlsnames its popup, often kept in the page while it is collapsed; - controlled elements that contain the element itself (a tree item naming its own group's parent).
Expectation. aria-expanded tells assistive technology whether the content the element controls is shown. When it says the opposite of what the page shows, a screen reader user is told a panel is closed while it is open, or the other way round.
aria-expanded="false", and every elementaria-controlsnames is shown: cantTell (EXPANDED_FALSE_CONTROLLED_SHOWN).aria-expanded="true", and every elementaria-controlsnames is hidden: cantTell (EXPANDED_TRUE_CONTROLLED_HIDDEN).- Otherwise: pass.
An element counts as hidden when it is out of the accessibility tree: display: none, visibility: hidden, hidden, a closed <details>, content-visibility: hidden, inert or aria-hidden="true" on it or an ancestor, and, in a browser, a box of its own collapsed to no height or width with its overflow clipped (an accordion panel animated with height: 0). A panel collapsed some other way (a transform, an ancestor's height) counts as shown, and the content a control expands may stay in view while collapsed (a paragraph cut to two lines by line-clamp), which is why a finding is a question.
What a finding reports.
ariaExpanded:trueorfalse, as the attribute says.controlledCount: how many elementsaria-controlsnames that were compared.
These data.details fields help to read and reproduce a finding. Apart from reasonCode and the few fields Output schema names as stable, they are not a stable contract: a field may be renamed or dropped in a minor release, so don’t build on them.
Examples
<button aria-expanded="false" aria-controls="shipping">Shipping</button><div id="shipping" hidden>Orders ship within two working days.</div>
The panel is hidden, as aria-expanded="false" says.
<button aria-expanded="false" aria-controls="shipping">Shipping</button><div id="shipping">Orders ship within two working days.</div>
aria-expanded="false" tells a screen reader the panel is closed, but it is shown. A person checks whether the panel is open, or whether the control only expands content that stays in view.
How to check
When this rule can’t decide, it reports cantTell and leaves the question to a person. Each question it can ask is listed here under its reason code, with the steps to answer it. A finding carries the same steps as howToCheck, in the scan’s language. See Output schema.
EXPANDED_FALSE_CONTROLLED_SHOWN
- Find the toggle the report names; it says it is collapsed.
- Look at the content it controls and check whether it is shown in full or only a preview, such as a few clamped lines.
- Activate the toggle with Enter or Space and check the Accessibility pane: the expanded state should follow what is shown.
Pass. The content is collapsed or only previewed while the toggle says collapsed, and the state changes when the content opens.
Fail. The content is fully shown while the toggle tells screen reader users it is collapsed, which fails WCAG 4.1.2.
EXPANDED_TRUE_CONTROLLED_HIDDEN
- Find the toggle the report names; it says it is expanded.
- Look for the content it controls and check whether it is shown on screen, waiting for any animation to finish.
- Activate the toggle with Enter or Space and check in the Accessibility pane that the expanded state follows what is shown.
Pass. The content is shown while the toggle says expanded, once any transition ends.
Fail. The content stays hidden while the toggle tells screen reader users it is expanded, which fails WCAG 4.1.2.