• Success Criterion 4.1.2
  • Conformance level A

Expanded State Attribute That Never Updates When Toggled

4.1.2 — Name, Role, Value

Scenario

Setting

A fitness app's workout tracker

What’s wrong

aria-expanded (the open/closed state in code) present but never updated by JS (state stuck).

Example

<button aria-expanded="false" onclick="toggleDetails('squat')">Squat: 3 sets</button>
<div id="squat-details" class="details open">45 lb, 12 reps, rest 60s</div>
<!-- clicking the button adds the "open" class and shows the div,
     but the script never touches aria-expanded -->

Why it matters

A screen reader user who opens the squat details still hears "collapsed" and may click again, hiding what they just opened.

How to test

Toggle a stateful control (expand, select, check) and watch DevTools live: if the state attribute doesn't change value, it fails.

How to fix

Update aria-expanded in the exact same function that toggles the visual "open" class.

function toggleDetails(id) {
  const btn = document.querySelector(`[data-target="${id}"]`);
  const isOpen = btn.getAttribute('aria-expanded') === 'true';
  btn.setAttribute('aria-expanded', String(!isOpen));
  document.getElementById(`${id}-details`).classList.toggle('open');
}

Outcome

A lifter opens the squat card and hears "expanded" confirming the sets are now visible.

Who is affected

Screen reader users tracking sets cannot trust the expand or collapse state of any exercise card.

Learn more