curriculum/challenges/english/blocks/lecture-understanding-aria-expanded-aria-live-and-common-aria-states/672a54ce90c19e9038f481d7.md
The aria-expanded attribute is used for accessibility purposes to indicate if a control is expanded or collapsed. It's used in conjunction with collapsible widgets like menus, accordions and other disclosure widgets that control the visibility of content. The aria-expanded attribute is set to true if the control is expanded, or false if it is collapsed.
The information provided by aria-expanded allows people using screen readers to understand the current state of the control (whether it is expanded or collapsed).
The aria-expanded attribute is applied to the interactive element that toggles the visibility of a collapsible widget. For example, if a button toggles an expandable menu, the aria-expanded attribute is placed on the button.
When the menu is expanded, the aria-expanded attribute should be set to true like in this example:
<button aria-expanded="true">Menu</button>
When the menu is collapsed, it should be set to false instead.
<button aria-expanded="false">Menu</button>
You must always have the aria-expanded attribute set to either true or false on the controlling element. For example, if a button toggles the visibility of a menu, the default value for aria-expanded should be based on the default visibility of the menu.
If the menu is expanded by default, aria-expanded should initially be set to true. If the menu is collapsed by default, aria-expanded should initially be set of false.
The value of aria-expanded should be updated dynamically using JavaScript as the user interacts with the element.
Additionally, the properties, aria-controls and aria-owns can be used in combination with aria-expanded to establish a programmatic connection between the controlling element and the element it controls.
Let's start with aria-controls. When used with aria-expanded, the aria-controls attribute is used to specify the element being controlled. For example, a button might expand or collapse a list acting as a menu. The value of aria-controls will be the id of the controlled element (the menu list in this example).
:::interactive_editor
<link rel="stylesheet" href="styles.css">
<button aria-expanded="false" aria-controls="menu1">Menu</button>
<ul id="menu1" hidden>
<li>...</li>
<li>...</li>
</ul>
<script src="index.js"></script>
button {
background-color: #0078d4;
color: white;
padding: 8px 12px;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #005ea2;
}
ul {
list-style: none;
padding: 0;
margin: 8px 0 0;
border: 1px solid #ccc;
border-radius: 4px;
width: 150px;
background: #fff;
}
li {
padding: 8px;
cursor: pointer;
}
li:hover {
background-color: #f2f2f2;
}
const button = document.querySelector('button');
const menu = document.getElementById(button.getAttribute('aria-controls'));
button.addEventListener('click', () => {
const expanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!expanded));
menu.hidden = expanded;
});
:::
Notice that the list immediately follows the controlling button. For expandable controls like this, it is best to have the expanded content immediately follow the element that controls it in the DOM. This prevents screen reader users from having to search for the expanded content, and makes it easier for keyboard users to navigate through any interactive controls in the expanded content.
If it is not possible to place the expanded content immediately after the controlling element, the aria-owns attribute allows you to virtually move it after the control in the accessibility tree. This allows assistive technology like screen readers to pretend the expanded content is placed directly after the control in the DOM.
:::interactive_editor
<link rel="stylesheet" href="styles.css">
<button aria-owns="menu1" aria-expanded="true">Menu</button>
<main>
<!-- an entire page worth of content --->
</main>
<ul id="menu1">
<li>...</li>
<li>...</li>
</ul>
<script src="index.js"></script>
button {
background-color: #0078d4;
color: white;
padding: 8px 12px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-bottom: 10px;
}
button:hover {
background-color: #005ea2;
}
ul {
list-style: none;
padding: 0;
margin: 8px 0;
border: 1px solid #ccc;
border-radius: 4px;
width: 150px;
background: #fff;
position: absolute;
z-index: 10;
}
li {
padding: 8px;
cursor: pointer;
}
li:hover {
background-color: #f2f2f2;
}
const button = document.querySelector('button');
const menu = document.getElementById(button.getAttribute('aria-owns'));
button.addEventListener('click', () => {
const expanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!expanded));
menu.hidden = expanded;
});
// Close the menu if user clicks outside
document.addEventListener('click', (e) => {
if (!button.contains(e.target) && !menu.contains(e.target)) {
button.setAttribute('aria-expanded', 'false');
menu.hidden = true;
}
});
:::
There are drawbacks to using the aria-owns attribute. It creates unnecessary verbosity for screen reader users since most screen readers will automatically read out the entire contents of the expanded element when first expanded. It also does not change the tab order, potentially forcing keyboard users to tab through all of the other interactive controls on the page before reaching the expanded content, unless you manage the tabbing order with JavaScript.
Ideally, the expandable content should be placed after the control element, and the aria-owns attribute should only be used in a worst case scenario when that is not possible. If it must be used, you will need to thoroughly test with a wide range of screen readers and browsers to ensure that your implementation is accessible for everyone.
And just a reminder, when you use either aria-controls or aria-owns, the value of aria-expanded must continue to be updated as the control is expanded and collapsed.
The aria-expanded attribute indicates whether a control is expanded or collapsed. This information is essential for screen reader users, helping them understand the current state of collapsible elements like menus, accordions, and other similar disclosure widgets.
By using aria-expanded correctly, you can create an intuitive user experience for everyone.
What is the primary purpose of the aria-expanded attribute?
To define the visual appearance of an element.
Think about how aria-expanded provides information to assistive technologies.
To improve website performance.
Think about how aria-expanded provides information to assistive technologies.
To indicate whether an element is expanded or collapsed.
To enhance browser compatibility.
Think about how aria-expanded provides information to assistive technologies.
3
When should the aria-expanded attribute be used?
For all elements on a web page.
Consider the context in which aria-expanded is most useful.
For elements that are visually hidden.
Consider the context in which aria-expanded is most useful.
For collapsible elements like menus and accordions.
For elements with dynamic content.
Consider the context in which aria-expanded is most useful.
3
What are the possible values for the aria-expanded attribute?
true, false, yes, no.
Think about the states an element can be in regarding expansion or collapse.
open, closed, expanded, collapsed.
Think about the states an element can be in regarding expansion or collapse.
show, hide, visible, invisible.
Think about the states an element can be in regarding expansion or collapse.
true, false.
4