Element.ariaControlsElements is an instance property that holds an array of elements controlled by the current element. Learn how it relates to aria-controls, why targets do not need an id when you set the property, and how to get or set the relationship from JavaScript—with five examples and try-it labs.
01
Kind
Instance property
02
Returns
HTMLElement[]
03
Writable
Yes (get / set)
04
Reflects
aria-controls
05
Status
Baseline 2025
06
Use for
Controlled regions
Fundamentals
Introduction
Many widgets control other parts of the page: a button that reveals panels, a combobox that opens a popup list, a scrollbar that scrolls a region. ARIA describes that link with aria-controls.
ariaControlsElements is the modern element-reference form: you work with real DOM nodes instead of managing id strings.
Think: “this control owns these regions.” Pair it with aria-expanded when the controlled content opens and closes.
Concept
Understanding the Property
MDN: the ariaControlsElements property of the Element interface is an array containing the elements that are controlled by the element it is applied to. For example, this might be set on a combobox to indicate the element that it pops up, or on a scrollbar to indicate the element it controls.
Get / set — read or assign an array of elements.
Flexible alternative to the aria-controls attribute.
No id required on targets when you set the property (MDN).
Reflection — reads valid in-scope id refs from the attribute; setting the property clears the attribute.
Foundation
📝 Syntax
JavaScript
ariaControlsElements
Value
An array of subclasses of HTMLElement, representing the elements that are controlled by this element.
When read, the returned array is static and read-only.
When written, the assigned array is copied—later edits to that array do not change the property.
Compare
⚖️ Property vs aria-controls Attribute
Attribute
Property
API
aria-controls="id1 id2"
el.ariaControlsElements
Points to
Space-separated id strings
Array of Element objects
Targets need id?
Yes
No (when set via property)
After you set the property
—
Corresponding attribute is cleared (MDN)
Pattern
📋 Button Controls Panels (MDN Shape)
MDN’s example uses a button that controls two panels listed in aria-controls:
JavaScript
<button id="toggleButton" aria-controls="panel1 panel2" aria-expanded="false">
Show Details
</button>
<div class="panel" id="panel1" aria-hidden="true">
<p>Panel1 opened/closed by button.</p>
</div>
<div class="panel" id="panel2" aria-hidden="true">
<p>Panel2 opened/closed by button.</p>
</div>
Related element-reference property: ariaActiveDescendantElement (single active descendant, not a controls list).
Detect support and read MDN’s button / panels example.
Example 1 — Feature-Detect
Check whether the reflected property exists.
JavaScript
if ("ariaControlsElements" in Element.prototype) {
console.log("ariaControlsElements is supported");
} else {
console.log("ariaControlsElements not supported by browser");
}
MDN: setting the property clears the corresponding attribute. Re-assign a new array when the controlled set changes—mutating the old array is not enough.
Example 4 — Attribute String vs Element Array
Compare getAttribute with the resolved element list.
Element.ariaControlsElements is Baseline Newly available (MDN: across latest browsers since April 2025). Feature-detect on older engines and keep an aria-controls id fallback if needed. Logos use the shared browser-image-sprite.png sprite from this project.
✓ Baseline 2025
Element.ariaControlsElements
HTMLElement[] — reflected aria-controls element references.
BaselineNewly available 2025
Google ChromeSupported in current releases — feature-detect older
Yes
Microsoft EdgeSupported in current releases — feature-detect older
Yes
Mozilla FirefoxSupported in current releases — feature-detect older
Yes
Apple SafariSupported in current releases — feature-detect older
Yes
OperaFollow Chromium support
Yes
Internet ExplorerNot supported — use aria-controls attribute
No
ariaControlsElementsBaseline
Bottom line: Detect "ariaControlsElements" in Element.prototype. Prefer element arrays for dynamic widgets. Fall back to aria-controls id strings when the property is missing. Re-assign arrays when the controlled set changes.
Wrap Up
Conclusion
ariaControlsElements lets you manage aria-controls relationships with real Element references instead of only id strings. Feature-detect on older browsers, keep open/close state in sync with aria-expanded, and re-assign the array when the controlled set changes.
Assign a fresh array when the controlled set changes
Keep id-based aria-controls as a fallback
Point only to elements that are actually controlled
❌ Don’t
Mutate a previously assigned array and expect updates
Assume every older browser exposes the IDL property
List unrelated elements just to fill the array
Forget visible open/close behavior for controlled panels
Confuse this with ariaActiveDescendantElement
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about ariaControlsElements
Reflected aria-controls as an array of element references.
5
Core concepts
📄01
Get / set
on Element
Kind
📝02
Element array
HTMLElement[]
Type
🔍03
No id needed
when property-set
Rule
✅04
Baseline
newly available
Status
🎯05
Detect
older browsers
Tip
❓ Frequently Asked Questions
An array of HTMLElement subclasses representing the elements controlled by this element (for example panels opened by a button).
No. MDN marks Element.ariaControlsElements as Baseline 2025 (newly available since April 2025). It is not Deprecated, Experimental, or Non-standard. Feature-detect on older browsers.
The attribute uses space-separated id strings. The property uses live Element references. Assigned elements do not need an id. Setting the property clears the corresponding attribute.
No. When read, the returned array is static and read-only. When written, the assigned array is copied—later changes to that array do not update the property.
For widgets that control other regions: disclosure buttons, combobox popups, tab panels, scrollbars, and similar aria-controls relationships.
Yes. Custom elements can use ElementInternals.ariaControlsElements for the same relationship from inside a component.
Did you know?
MDN notes that when you readariaControlsElements, you get a static, read-only array—and when you write, the assigned array is copied. Pushing into an old array later will not update the relationship.