JavaScript Element ariaActiveDescendantElement Property

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

What You’ll Learn

Element.ariaActiveDescendantElement is an instance property that points to the current active descendant for widgets like listboxes and comboboxes. Learn how it relates to aria-activedescendant, why you can skip giving the target an id, how get/set reflection works, and how to feature-detect—with five examples and try-it labs.

01

Kind

Instance property

02

Returns

HTMLElement | null

03

Writable

Yes (get / set)

04

Reflects

aria-activedescendant

05

Status

Baseline 2025

06

Use for

Composite widgets

Introduction

In many ARIA widgets, keyboard focus stays on a container (for example a listbox) while a child option is the “active” one announced to assistive technology. The classic way to express that is the aria-activedescendant attribute with an id string.

ariaActiveDescendantElement is the modern element reference form of the same idea: you assign (or read) a real DOM element instead of managing unique ids. MDN: unlike the attribute, the assigned element does not have to have an id.

JavaScript
listbox.ariaActiveDescendantElement = optionElement;
console.log(listbox.ariaActiveDescendantElement?.textContent);
💡
Beginner tip

Think: “focus is on the widget; the active descendant is which option is highlighted.” That is what screen readers need for many listbox patterns.

Understanding the Property

MDN: the ariaActiveDescendantElement property of the Element interface represents the current active element when focus is on a composite widget, combobox, textbox, group, or application.

  • Get / set — read the active descendant, or assign one (or null).
  • Flexible alternative to the aria-activedescendant attribute.
  • No id required on the target when you set the property.
  • Reflection — reads valid in-scope id refs from the attribute; setting the property clears the attribute.

📝 Syntax

JavaScript
ariaActiveDescendantElement

Value

A subclass of HTMLElement that represents the active descendant, or null if there is no active descendant.

⚖️ Property vs aria-activedescendant Attribute

AttributeProperty
APIaria-activedescendant="id"el.ariaActiveDescendantElement
Points toId stringElement object
Target needs id?YesNo (when set via property)
After you set the propertyCorresponding attribute is cleared (MDN)

MDN: the property reflects the attribute when it is defined, but only for reference id values that match valid in-scope elements.

📋 MDN Listbox Shape

MDN’s example uses a role="listbox" container with aria-activedescendant pointing at an option id:

JavaScript
<div id="streetType" role="listbox" aria-activedescendant="avenue">
  <div>Street</div>
  <div id="avenue">Avenue</div>
  <div>Lane</div>
</div>

With the property supported, you can read the live element and its text without parsing the id string yourself.

⚡ Quick Reference

GoalCode / note
Feature-detect"ariaActiveDescendantElement" in Element.prototype
Read active optionlistbox.ariaActiveDescendantElement
Set active optionlistbox.ariaActiveDescendantElement = option
Clearlistbox.ariaActiveDescendantElement = null
Classic attributegetAttribute("aria-activedescendant")
MDN statusBaseline 2025 (newly available)

🔍 At a Glance

Four facts about ariaActiveDescendantElement.

Kind
get / set

Instance

Returns
Element

or null

ARIA
activedesc.

Reflected

Baseline
2025

Newly available

Examples Gallery

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

📚 Getting Started

Detect support and read MDN’s listbox example.

Example 1 — Feature-Detect

Check whether the reflected property exists.

JavaScript
if ("ariaActiveDescendantElement" in Element.prototype) {
  console.log("ariaActiveDescendantElement is supported");
} else {
  console.log("ariaActiveDescendantElement not supported by browser");
}
Try It Yourself

How It Works

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

Example 2 — Get the Active Descendant (MDN)

Read the attribute id, the element property, and the option text.

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

if ("ariaActiveDescendantElement" in Element.prototype) {
  console.log("getAttribute():", streetType.getAttribute("aria-activedescendant"));
  console.log("ariaActiveDescendantElement:", streetType.ariaActiveDescendantElement);
  console.log("text:", streetType.ariaActiveDescendantElement?.textContent.trim());
} else {
  console.log("ariaActiveDescendantElement not supported by browser");
}

// HTML (MDN):
// <div id="streetType" role="listbox" aria-activedescendant="avenue">
//   <div>Street</div>
//   <div id="avenue">Avenue</div>
//   <div>Lane</div>
// </div>
Try It Yourself

How It Works

The attribute still holds the id string; the property resolves it to the live HTMLDivElement.

📈 Set, Clear & Snapshot

Assign options without ids, clear the relationship, and inspect support.

Example 3 — Set Without Requiring an id

Point the listbox at an option element directly.

JavaScript
const listbox = document.createElement("div");
listbox.setAttribute("role", "listbox");
const optA = document.createElement("div");
optA.textContent = "Street";
const optB = document.createElement("div");
optB.textContent = "Avenue";
listbox.append(optA, optB);
document.body.appendChild(listbox);

if (!("ariaActiveDescendantElement" in listbox)) {
  console.log("Property not supported — fall back to aria-activedescendant ids");
} else {
  listbox.ariaActiveDescendantElement = optB;
  console.log({
    text: listbox.ariaActiveDescendantElement.textContent,
    attrAfterSet: listbox.getAttribute("aria-activedescendant"),
    note: "Setting the property clears the attribute (MDN)"
  });
}
Try It Yourself

How It Works

Neither option needed an id. Arrow-key handlers can reassign the property as the highlight moves.

Example 4 — Clear with null

Remove the active-descendant relationship.

JavaScript
const widget = document.createElement("div");
widget.setAttribute("role", "listbox");
const item = document.createElement("div");
item.textContent = "Lane";
widget.appendChild(item);
document.body.appendChild(widget);

if (!("ariaActiveDescendantElement" in widget)) {
  console.log("Property not supported");
} else {
  widget.ariaActiveDescendantElement = item;
  console.log("before clear:", widget.ariaActiveDescendantElement?.textContent);
  widget.ariaActiveDescendantElement = null;
  console.log("after clear:", widget.ariaActiveDescendantElement);
}
Try It Yourself

How It Works

Assign null when the widget no longer has an active option (for example after closing a popup list).

Example 5 — Support Snapshot

One object summarizing detection and a quick listbox read.

JavaScript
const supported = "ariaActiveDescendantElement" in Element.prototype;
console.log({
  supported,
  descriptor: supported
    ? typeof Object.getOwnPropertyDescriptor(Element.prototype, "ariaActiveDescendantElement")
    : "n/a",
  tip: "Prefer element refs for dynamic widgets; keep attribute fallback for older browsers",
  status: "Baseline 2025 — newly available (feature-detect older engines)"
});
Try It Yourself

How It Works

Baseline 2025 means latest browsers agree—older devices may still need the classic attribute pattern.

🚀 Common Use Cases

  • Listbox / menu keyboard navigation without inventing unique option ids.
  • Combobox popup option highlight while focus stays on the input.
  • Updating the active option across Shadow DOM where idrefs are awkward.
  • Migrating widgets from string aria-activedescendant to element refs.
  • Custom elements via ElementInternals.ariaActiveDescendantElement.

🔧 How It Works

1

Focus stays on the composite widget

Listbox, combobox, or similar container is focused.

Focus
2

You set the active descendant

Assign an Element (or keep an attribute idref).

Set
3

Assistive tech reads the relationship

The active option is announced as the user arrows.

A11y
4

Reassign as selection moves

Update the property on each highlight change.

📝 Notes

  • Not Deprecated, Experimental, or Non-standard on MDN (Baseline 2025).
  • Still feature-detect on older browsers.
  • Setting the property clears aria-activedescendant (MDN).
  • Also available on ElementInternals for custom elements.
  • Related: activeViewTransition, Node, EventTarget, JavaScript hub.

Browser Support

Element.ariaActiveDescendantElement is Baseline 2025 (newly available since April 2025). Feature-detect on older engines and keep an aria-activedescendant id fallback if needed. Logos use the shared browser-image-sprite.png sprite from this project.

Baseline 2025

Element.ariaActiveDescendantElement

HTMLElement or null — reflected aria-activedescendant element reference.

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-activedescendant attribute
No
ariaActiveDescendantElement Baseline

Bottom line: Detect "ariaActiveDescendantElement" in Element.prototype. Prefer element assignment for dynamic widgets. Fall back to aria-activedescendant ids when the property is missing.

Conclusion

ariaActiveDescendantElement lets you manage the active option of a composite widget with a real Element reference instead of only id strings. Feature-detect on older browsers, and keep accessibility behavior correct whether you use the property or the classic attribute.

Continue with ariaAtomic, EventTarget, Node, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Feature-detect before reading or writing the property
  • Update the property when keyboard highlight moves
  • Keep correct roles (listbox, options, etc.)
  • Use element refs when generating many dynamic options
  • Test with a screen reader for your widget pattern

❌ Don’t

  • Assume every older browser has the property
  • Forget a fallback to aria-activedescendant ids when needed
  • Point at an out-of-scope element and expect reflection to work
  • Skip ARIA roles and keyboard behavior for the widget
  • Confuse DOM focus with the active descendant relationship

Key Takeaways

Knowledge Unlocked

Five things to remember about ariaActiveDescendantElement

Reflected Element reference for aria-activedescendant.

5
Core concepts
🎨 02

HTMLElement

or null

Value
🔗 03

No id needed

when set via JS

Benefit
04

Baseline 2025

newly available

Status
🎯 05

Fallback

attribute ids

Compat

❓ Frequently Asked Questions

An HTMLElement (subclass) that is the current active descendant for a composite widget, or null if there is none.
No. MDN marks it Baseline 2025 (newly available since April 2025). It is not Deprecated, Experimental, or Non-standard. Older browsers may still lack it—feature-detect.
The attribute uses an id string. The property uses a live Element reference. The referenced element does not need an id. Setting the property clears the corresponding attribute.
For listboxes, comboboxes, and similar widgets where focus stays on a container while a child option is the “active” one for assistive tech.
Yes. Assign an Element (or null). MDN: if you set the property, the aria-activedescendant attribute is cleared.
Yes. Custom elements can use ElementInternals.ariaActiveDescendantElement for the same relationship from inside a component.
Did you know?

Reflected element references were designed partly for Shadow DOM: classic idrefs cannot cross shadow boundaries, but assigning ariaActiveDescendantElement can still connect a host control to an option inside a shadow tree when the platform supports it.

Next: Element ariaAtomic

Learn the reflected aria-atomic property for live regions.

ariaAtomic →

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