About This HTML Issue
The validator error occurs when an element such as an a, button, or custom widget includes aria-controls="" (empty) or whitespace-only. The aria-controls attribute takes one or more space-separated id values (IDREFS). Each referenced id must exist exactly once in the same document. Leaving it empty violates the ARIA and HTML requirements and provides no usable relationship for assistive technologies.
Why this matters:
-
Accessibility: Screen readers rely on
aria-controlsto announce relationships between controls and controlled regions (e.g., a toggle and its panel). An empty value misleads AT or adds noise. -
Standards compliance: HTML and ARIA require at least one non-whitespace
id. Empty values cause validation failures. - Robustness: Incorrect references can confuse scripts and future maintainers, and break behavior when IDs change.
How to fix it:
-
Only add
aria-controlswhen the element truly controls another region (show/hide, sort, update). -
Ensure the controlled element has a unique
id. -
Set
aria-controlsto thatid(or multiple space-separated IDs). - Keep the reference in sync if IDs change.
-
If nothing is controlled, remove
aria-controlsentirely.
Examples
Invalid: empty aria-controls (triggers the error)
<a href="#" aria-controls="">Toggle details</a>
Valid: control a single region
<div id="details-panel" hidden>
Some details...
</div>
<a href="#details-panel" aria-controls="details-panel">Toggle details</a>
Valid: control multiple regions (space-separated IDs)
<section id="filters" hidden>...</section>
<section id="results" hidden>...</section>
<button type="button" aria-controls="filters results">Show filters and results</button>
Valid: remove when not needed
<a href="#">Toggle details</a>
Minimal complete document with proper usage
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>aria-controls Example</title>
</head>
<body>
<button type="button" aria-controls="info" aria-expanded="false">Toggle info</button>
<div id="info" hidden>
Extra information.
</div>
<script>
const btn = document.querySelector('button');
const panel = document.getElementById(btn.getAttribute('aria-controls'));
btn.addEventListener('click', () => {
const expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', String(!expanded));
panel.hidden = expanded;
});
</script>
</body>
</html>
Tips:
-
Use
aria-controlsfor functional relationships (control affects content), not just visual proximity. -
Combine with
aria-expandedwhen toggling visibility to convey state. -
Verify that every
idinaria-controlsexists and is unique; avoid dynamic mismatches created by templating or component reuse.
Learn more:
Last reviewed: February 13, 2026
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.