Signatur
Beschreibung
ariaActiveDescendantElement ist die Elementreferenz-Variante des ARIA-Attributs aria-activedescendant. Die Eigenschaft gibt an, welches untergeordnete Element gerade aktiv ist, während der eigentliche Tastaturfokus auf dem Container-Element bleibt. Das betrifft zum Beispiel eine combobox, eine textbox, eine group, eine application oder zusammengesetzte Widgets wie listbox, grid, tree und menu. Screenreader lesen dann die aktive Option vor, obwohl sie selbst keinen Fokus hat.
Das Attribut braucht eine id als Verweis. Die Eigenschaft nimmt dagegen direkt ein Element-Objekt an. Deshalb musst du keine eindeutigen IDs erzeugen und verwalten. Außerdem kann ein Element in einem Shadow Root auf ein Element im umgebenden Light DOM verweisen (also in einem Vorfahren-Baum). Mit reinen ID-Verweisen geht das nicht.
Setzt du die Eigenschaft, schreibt der Browser aria-activedescendant="" (leerer String) in das Attribut. Die eigentliche Verknüpfung speichert er intern. Lies die Beziehung deshalb immer über die Eigenschaft aus und nicht über getAttribute(). Setzt du die Eigenschaft auf null, entfernt der Browser das Attribut. Ist nur das Attribut mit einer gültigen id gesetzt, liefert der Getter das passende Element aus demselben Baum.
Für benutzerdefinierte Elemente gibt es das Gegenstück ElementInternals.ariaActiveDescendantElement. Darüber legt eine Komponente einen Standardwert fest, ohne ein sichtbares Attribut am Host zu setzen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value | Element | null | null | Nur beim Setzen: das Element, das als aktiver Nachkomme gelten soll. null entfernt die Beziehung und das Attribut. |
Rückgabewert
null, wenn keines gesetzt ist oder das Element aus dem Geltungsbereich des Verweises verschwunden ist (z. B. aus dem DOM entfernt oder in einem nicht zugänglichen Shadow Root).Beispiele
Listbox mit Pfeiltasten steuern
// HTML: <ul id="liste" role="listbox" tabindex="0">
// <li role="option">Apfel</li><li role="option">Birne</li><li role="option">Kirsche</li>
// </ul>
const liste = document.getElementById('liste');
const optionen = [...liste.querySelectorAll('[role="option"]')];
let index = 0;
const aktivieren = (i) => {
optionen.forEach((o) => o.removeAttribute('aria-selected'));
optionen[i].setAttribute('aria-selected', 'true');
liste.ariaActiveDescendantElement = optionen[i]; // keine id nötig
optionen[i].scrollIntoView({ block: 'nearest' });
};
liste.addEventListener('keydown', (e) => {
if (e.key === 'ArrowDown') index = Math.min(index + 1, optionen.length - 1);
else if (e.key === 'ArrowUp') index = Math.max(index - 1, 0);
else return;
e.preventDefault();
aktivieren(index);
console.log(liste.ariaActiveDescendantElement.textContent);
});
aktivieren(0);
Attribut und Eigenschaft im Vergleich
const input = document.createElement('input');
input.setAttribute('role', 'combobox');
const option = document.createElement('div');
option.id = 'opt-1';
document.body.append(input, option);
// Variante 1: klassisch per id
input.setAttribute('aria-activedescendant', 'opt-1');
console.log(input.ariaActiveDescendantElement === option);
// Variante 2: direkte Elementreferenz
input.ariaActiveDescendantElement = option;
console.log(JSON.stringify(input.getAttribute('aria-activedescendant')));
// Entfernen
input.ariaActiveDescendantElement = null;
console.log(input.hasAttribute('aria-activedescendant'));
Feature-Erkennung mit Fallback auf id
const setzeAktiv = (container, element) => {
if ('ariaActiveDescendantElement' in Element.prototype) {
container.ariaActiveDescendantElement = element;
} else {
element.id ||= `ad-${crypto.randomUUID()}`;
container.setAttribute('aria-activedescendant', element.id);
}
};
const box = document.querySelector('[role="listbox"]');
if (box) setzeAktiv(box, box.firstElementChild);
// Wichtig · Fallstricke
- Browserunterstützung: Die ARIA-Elementreflexion gibt es erst seit Safari 16.4, Chrome/Edge 135 und Firefox 136. Für ältere Browser prüfst du die Unterstützung und greifst auf
aria-activedescendantmit eineridzurück. - Attributwert ist leer: Nach dem Setzen über die Eigenschaft liefert
getAttribute('aria-activedescendant')nur"". Die Beziehung lässt sich daraus nicht rekonstruieren. Auch Selektoren wie[aria-activedescendant=\"x\"]greifen dann nicht mehr. - Shadow-DOM-Grenzen: Ein Verweis funktioniert nur auf Elemente im selben Baum oder in einem Vorfahren-Baum. Ein Element aus dem Light DOM kann nicht in einen fremden Shadow Root hineinverweisen. In diesem Fall liefert der Getter
null. - Nur Semantik, kein Fokus: Die Eigenschaft verschiebt weder den Fokus, noch scrollt sie, noch ändert sie das Aussehen. Den Container fokussierbar machen (
tabindex=\"0\"), die aktive Option hervorheben undscrollIntoView()aufrufen musst du selbst. - Das referenzierte Element sollte ein Nachkomme sein oder über
aria-ownsbzw.aria-controlszugeordnet sein und eine passende Rolle haben (z. B.option). Sonst kündigen assistive Technologien es womöglich nicht an. - Wird das referenzierte Element aus dem DOM entfernt, liefert der Getter
null. Setze den Verweis nach dem Neuaufbau der Liste neu.