JavaScript Element ariaControlsElements Property

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Baseline 2025
Instance property

What You’ll Learn

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

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.

JavaScript
const controlled = toggleButton.ariaControlsElements;
controlled.forEach((el) => console.log(el.textContent.trim()));
💡
Beginner tip

Think: “this control owns these regions.” Pair it with aria-expanded when the controlled content opens and closes.

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.

📝 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.

⚖️ Property vs aria-controls Attribute

AttributeProperty
APIaria-controls="id1 id2"el.ariaControlsElements
Points toSpace-separated id stringsArray of Element objects
Targets need id?YesNo (when set via property)
After you set the propertyCorresponding attribute is cleared (MDN)

📋 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).

⚡ Quick Reference

GoalCode / note
Feature-detect"ariaControlsElements" in Element.prototype
Readel.ariaControlsElements
Writeel.ariaControlsElements = [panel1, panel2]
Attribute formaria-controls="panel1 panel2"
MDN statusBaseline Newly available (Apr 2025)

🔍 At a Glance

Four facts about Element.ariaControlsElements.

Kind
get / set

Instance

Type
HTMLElement[]

Static copy

ARIA
aria-controls

Reflected

Baseline
2025

Newly available

Examples Gallery

Examples follow MDN Element: ariaControlsElements. Labs feature-detect first so older browsers still show a clear message.

📚 Getting Started

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");
}
Try It Yourself

How It Works

Matches MDN’s feature test before reading or writing the property.

Example 2 — Get Controlled Elements (MDN)

Read the attribute ids, then the element array and each panel’s text.

JavaScript
const toggleButton = document.getElementById("toggleButton");

console.log("aria-controls:", toggleButton.getAttribute("aria-controls"));

if ("ariaControlsElements" in Element.prototype) {
  const controlled = toggleButton.ariaControlsElements;
  console.log("count:", controlled.length);
  controlled.forEach((el) => {
    console.log("text:", el.textContent.trim());
  });
} else {
  console.log("ariaControlsElements not supported by browser");
}
Try It Yourself

How It Works

The property resolves valid in-scope id references from aria-controls into real element objects.

📈 Set Array, Attribute Sync & Snapshot

Assign element references and verify reflection rules.

Example 3 — Set an Array of Elements

Assign controlled panels without relying on id strings in script.

JavaScript
const btn = document.createElement("button");
const a = document.createElement("div");
const b = document.createElement("div");
a.textContent = "Panel A";
b.textContent = "Panel B";
document.body.append(btn, a, b);

if ("ariaControlsElements" in Element.prototype) {
  btn.ariaControlsElements = [a, b];
  console.log({
    count: btn.ariaControlsElements.length,
    attrAfterSet: btn.getAttribute("aria-controls"), // cleared when property is set (MDN)
    texts: btn.ariaControlsElements.map((el) => el.textContent)
  });
} else {
  console.log("ariaControlsElements not supported by browser");
}
Try It Yourself

How It Works

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.

JavaScript
const btn = document.getElementById("toggleButton");

console.log({
  fromAttribute: btn.getAttribute("aria-controls"),
  supported: "ariaControlsElements" in Element.prototype,
  fromProperty: "ariaControlsElements" in Element.prototype
    ? btn.ariaControlsElements.map((el) => el.id)
    : null
});
Try It Yourself

How It Works

Prefer the property in modern script; keep the attribute for HTML and older engines that only understand ids.

Example 5 — Support Snapshot

Remember the static-array and feature-detect rules.

JavaScript
console.log({
  supported: "ariaControlsElements" in Element.prototype,
  tip: "Returned array is static/read-only; assigned arrays are copied",
  pairsWith: "aria-expanded for open/close widgets",
  status: "Baseline Newly available (MDN, Apr 2025)"
});
Try It Yourself

How It Works

Fall back to aria-controls id strings when the property is missing.

🚀 Common Use Cases

  • Disclosure buttons that show or hide one or more panels.
  • Combobox widgets that control a popup listbox.
  • Tabs that control their associated tabpanels.
  • Scrollbars or other widgets that control a scroll region.
  • Custom elements via ElementInternals.ariaControlsElements.

🔧 How It Works

1

A control owns other regions

Button, combobox, tab, scrollbar, and so on.

Control
2

Declare the relationship

aria-controls ids or ariaControlsElements array.

Link
3

Assistive tech follows the link

Users can discover what the control affects.

A11y
4

JS updates the element list

Assign a new array when the controlled set changes.

📝 Notes

  • Not Deprecated, Experimental, or Non-standard on MDN (Baseline Newly available, Apr 2025).
  • Feature-detect on older browsers.
  • Returned arrays are static; assigned arrays are copied.
  • Related: ariaCurrent, ariaColSpan, EventTarget, JavaScript hub.

Browser Support

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.

Baseline Newly available 2025
Google Chrome Supported in current releases — feature-detect older
Yes
Microsoft Edge Supported in current releases — feature-detect older
Yes
Mozilla Firefox Supported in current releases — feature-detect older
Yes
Apple Safari Supported in current releases — feature-detect older
Yes
Opera Follow Chromium support
Yes
Internet Explorer Not supported — use aria-controls attribute
No
ariaControlsElements Baseline

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.

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.

Continue with ariaCurrent, ariaColSpan, EventTarget, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Feature-detect before using the property
  • Pair with aria-expanded for disclosures
  • 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

Key Takeaways

Knowledge Unlocked

Five things to remember about ariaControlsElements

Reflected aria-controls as an array of element references.

5
Core concepts
📝 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 read ariaControlsElements, 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.

Next: Element ariaCurrent

Learn the reflected aria-current property for navigation, steps, and breadcrumbs.

ariaCurrent →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful