aria-expanded aria-controls for Toggles
Build accessible disclosure and accordion widgets with ARIA.
aria-expanded aria-controls for Toggles is a free HTML Academy lesson on CoddyKit. This is lesson 1 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, and your progress syncs across the web and the CoddyKit app. The HTML Academy course includes 4 lessons in total.
Toggle Pattern Overview
Toggle controls (accordions, dropdowns, menus) need ARIA to communicate their open/closed state:
aria-expanded— indicates open/closed state of a controlaria-controls— links the control to the element it controls
aria-expanded
aria-expanded communicates whether a controlled element is expanded or collapsed:
<button aria-expanded="false" aria-controls="menu">
Menu
</button>
<ul id="menu" hidden>
<li><a href="/">Home</a></li>
</ul>
<script>
btn.addEventListener('click', () => {
const expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', !expanded);
menu.hidden = expanded;
});
</script>aria-controls
aria-controls references the id of the element that is controlled:
<button
id="details-btn"
aria-expanded="false"
aria-controls="details-panel"
>
Show Details
</button>
<div id="details-panel" hidden>
<p>Additional details go here...</p>
</div>
<!-- Screen reader: 'Show Details, button, collapsed'
After click: 'Show Details, button, expanded' -->Accordion Pattern
Accessible accordion with aria-expanded:
<div class="accordion">
<h3>
<button
aria-expanded="false"
aria-controls="panel-1"
>Section 1</button>
</h3>
<div id="panel-1" hidden>
<p>Panel 1 content...</p>
</div>
<h3>
<button
aria-expanded="false"
aria-controls="panel-2"
>Section 2</button>
</h3>
<div id="panel-2" hidden>
<p>Panel 2 content...</p>
</div>
</div>Dropdown Menu Pattern
Accessible navigation dropdown:
<nav>
<button
aria-expanded="false"
aria-haspopup="true"
aria-controls="products-menu"
>Products</button>
<ul id="products-menu" role="menu" hidden>
<li role="menuitem"><a href="/widget">Widget</a></li>
<li role="menuitem"><a href="/gadget">Gadget</a></li>
</ul>
</nav>aria-haspopup
aria-haspopup hints that activating the control will open a popup:
<button aria-haspopup="menu">File</button>
<!-- Values: true (menu), menu, listbox, tree, grid, dialog -->
<!-- Screen reader: 'File, button, has popup' -->
<!-- Note: aria-haspopup="true" is equivalent to "menu" -->
<!-- Use specific values when the popup type matters -->Details/Summary ARIA Supplement
The native details/summary already communicates expansion state — no ARIA needed:
<details>
<summary>FAQ Question</summary>
<p>Answer goes here.</p>
</details>
<!-- Browser automatically provides aria-expanded
and the disclosure widget semantics -->
<!-- No need to add aria-expanded manually to summary -->CSS for aria-expanded State
Use aria-expanded as a CSS hook:
/* Panel hidden by default: */
[aria-controls] + [hidden] {
display: none;
}
/* Or using aria-expanded on the button: */
[aria-expanded="false"] + .panel {
display: none;
}
[aria-expanded="true"] + .panel {
display: block;
}
/* Rotate arrow icon: */
[aria-expanded="true"] .arrow {
transform: rotate(180deg);
}Keyboard Requirements for Toggles
Toggle components must support keyboard interaction:
- Enter or Space — activate the toggle button
- Escape — close a dropdown or menu
- Arrow keys — navigate within an open menu
Managing Focus After Toggle
After toggling content, manage focus appropriately:
// Accordion: focus stays on the button (usually OK)
// Dropdown menu: move focus to first menu item on open
button.addEventListener('click', () => {
const expanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', !expanded);
panel.hidden = expanded;
if (!expanded) {
// Opening a dropdown: focus first item
panel.querySelector('a, button, [tabindex]')?.focus();
}
});Mobile Considerations
Toggle components on mobile:
- Touch targets must be at least 44×44px (WCAG 2.5.5)
- aria-expanded is supported by mobile screen readers (iOS VoiceOver, Android TalkBack)
- Swipe gestures do not replace keyboard/button activation
Quick Check
What value should aria-expanded have when the controlled section is hidden?
Recap: aria-expanded and aria-controls
Toggle ARIA essentials:
aria-expanded="true/false"— open/closed state of controlaria-controls="id"— links control to its panelaria-haspopup— hints a popup is available- Update aria-expanded on every toggle
- Move focus into opened menu; return to trigger on close
Learn HTML with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 40
- Lessons
- 159
Frequently Asked Questions
Is the “aria-expanded aria-controls for Toggles” lesson free?
Yes — any 3 lessons of the HTML Academy learning path, including “aria-expanded aria-controls for Toggles”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The HTML Academy course includes 4 lessons in total.
What will I learn in “aria-expanded aria-controls for Toggles”?
Build accessible disclosure and accordion widgets with ARIA. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start HTML Academy?
No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 1 of 4.
How long does the “aria-expanded aria-controls for Toggles” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this HTML Academy lesson?
Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- aria-expanded aria-controls for Toggles
- aria-selected and Tab Patterns
- Live Regions aria-live aria-atomic aria-relevant
- Testing with Screen Readers