References

Beginner-friendly references for web development, with live, editable examples.

The HTML aria-controls attribute

ARIA Accessibility
In short

Use aria-controls to name, by id, the element a control changes, such as the panel behind a tab. It takes one id or a space-separated list. The link is information only, so your script still does the opening, closing or updating.

Overview

The aria-controls attribute points from a control to the element or elements whose contents or presence it changes. A table of contents that drives a document pane fits that description, and so do checkboxes that choose which prices a table tracks and a tab that shows its panel.

A button with aria-controls doesn't open its target when clicked, so that work stays with your script. In the accessibility tree the link appears as a relation, and the target stays under its DOM parent.

WAI-ARIA 1.2 requires it on the combobox and scrollbar roles. It's also required when aria-autocomplete is list or both, where it points at the element that holds the suggestions.

The target can start out hidden. Pointing a combobox at its popup before the popup is shown is valid, and easier to program than adding the link later. Neither Chrome's nor Firefox's tree shows a relation to a target with the hidden attribute until it's rendered.

A <details> element shows and hides its own content with no id to point at. For an input of a text type that has a list attribute, the HTML-AAM spec maps a matching aria-controls value, but neither browser's tree shows that link.

Syntax

<button aria-expanded="false" aria-controls="faq-1">Shipping</button>
<div id="faq-1" hidden>Orders leave the warehouse in two days.</div>

Values

Value
A space-separated list of element id values.

Example

Live example
<p style="margin:0 0 8px">Check the box. The script updates both elements named in aria-controls, because the attribute changes nothing by itself.</p>
<label><input id="archived" type="checkbox" aria-controls="projects total"> Show archived projects</label>
<ul id="projects" style="margin:8px 0">
  <li>Website refresh</li>
  <li>Mobile app</li>
  <li hidden>Spring campaign</li>
  <li hidden>Old blog</li>
</ul>
<p id="total" style="margin:8px 0">Showing 2 of 4 projects</p>
<p id="state" role="status" style="margin:8px 0 0">Nothing updated yet.</p>
<script>
const box = document.getElementById('archived');
const state = document.getElementById('state');
box.addEventListener('change', () => {
  const ids = box.getAttribute('aria-controls').split(' ');
  const [projects, total] = ids.map(id => document.getElementById(id));
  const archived = [...projects.children].slice(2);
  archived.forEach(item => { item.hidden = !box.checked; });
  total.textContent = 'Showing ' + (box.checked ? 4 : 2) + ' of 4 projects';
  state.textContent = 'The script updated #' + ids.join(' and #') + '.';
});
</script>

Best practices

  • Pair aria-controls with aria-expanded on a button that shows and hides content. The first names the target, and the second reports whether it's open.
  • List every element one control changes, separated by spaces. A filter that updates a table and a result count would name both.
  • Recheck ids after a re-render. A reference that matches no element is ignored, so a stale id fails without an error.
  • Keep it for elements the control modifies. Help text that only explains the control isn't changed by it, so it belongs in aria-describedby.
  • Point each role="tab" at its tabpanel with aria-controls, so every tab names the panel it shows.

Frequently asked questions

Which elements does aria-controls connect?
The aria-controls attribute connects a control to each element it changes, such as a tab and its panel. It describes that link and doesn't make the change.
Is aria-controls required?
The aria-controls attribute is required in a few cases, and the WAI-ARIA 1.3 Working Draft narrows them. It drops the 1.2 rules for the combobox and scrollbar roles but keeps the one for aria-autocomplete set to list or both.
What does a list of ids in aria-controls mean?
A list of ids in aria-controls means the control affects all of those elements.
How is aria-controls presented to users?
No single presentation is required for aria-controls, so it's up to the browser and assistive technology. The WAI-ARIA 1.3 draft says the link can tell users they've revealed something, and that a user agent may convey several controlled elements, let the user move between them, or both.
Does aria-controls overlap with aria-owns?
No, aria-controls marks what a control changes, while aria-owns marks a parent and child relationship. A control can name several targets with aria-controls, while an element can have only one explicit owner.