Signatur
Beschreibung
Die Eigenschaft ariaOwnsElements von ElementInternals enthält ein Array von Elementen, die einem Custom Element im Barrierefreiheitsbaum als (zusätzliche) Kinder zugeordnet werden. Das ist nötig, wenn die DOM-Hierarchie nicht der logischen Beziehung zwischen Eltern- und Kindelement entspricht, etwa wenn die Popup-Liste einer Combobox aus technischen Gründen am Ende von document.body hängt.
Anders als das Attribut aria-owns, das eine durch Leerzeichen getrennte Liste von IDs erwartet, arbeitet die Eigenschaft direkt mit Elementobjekten. Man braucht also keine IDs zu vergeben. Weil sie über ElementInternals gesetzt wird, legt sie die Standard-Semantik des Custom Elements fest: Sie ist nicht als Attribut im DOM sichtbar, und Nutzer der Komponente können sie jederzeit mit einem eigenen aria-owns-Attribut am Host überschreiben.
Typischerweise setzt man den Wert im Konstruktor oder in connectedCallback(), nachdem man mit this.attachInternals() das ElementInternals-Objekt geholt hat. Wenn man null zuweist, wird die Beziehung wieder aufgehoben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value | Array<Element> | null | null | Wert, der beim Setzen zugewiesen wird: ein Array von Elementen, die das Custom Element besitzen soll. Mit null wird die Zuordnung entfernt. |
Rückgabewert
null, wenn nichts gesetzt ist. Ungültige Referenzen, etwa Elemente außerhalb des erlaubten Geltungsbereichs, werden beim Lesen herausgefiltert.Beispiele
Custom Combobox besitzt ein ausgelagertes Listbox-Popup
class MyCombobox extends HTMLElement {
#internals;
#listbox;
constructor() {
super();
this.#internals = this.attachInternals();
this.#internals.role = 'combobox';
}
connectedCallback() {
// Popup hängt aus Layout-Gründen direkt am body
this.#listbox = document.createElement('ul');
this.#listbox.setAttribute('role', 'listbox');
['Berlin', 'Hamburg', 'München'].forEach((stadt) => {
const li = document.createElement('li');
li.setAttribute('role', 'option');
li.textContent = stadt;
this.#listbox.append(li);
});
document.body.append(this.#listbox);
// Logische Beziehung für Screenreader herstellen
this.#internals.ariaOwnsElements = [this.#listbox];
}
disconnectedCallback() {
this.#internals.ariaOwnsElements = null;
this.#listbox?.remove();
}
}
customElements.define('my-combobox', MyCombobox);
Wert lesen und korrekt ergänzen
class OwnerBox extends HTMLElement {
internals = this.attachInternals();
addOwned(el) {
const aktuell = this.internals.ariaOwnsElements ?? [];
// Das zurückgegebene Array ist eingefroren – neues Array zuweisen
this.internals.ariaOwnsElements = [...aktuell, el];
}
}
customElements.define('owner-box', OwnerBox);
const box = document.createElement('owner-box');
document.body.append(box);
const a = document.createElement('div');
const b = document.createElement('div');
document.body.append(a, b);
box.addOwned(a);
box.addOwned(b);
console.log(box.internals.ariaOwnsElements.length);
console.log(Object.isFrozen(box.internals.ariaOwnsElements));
Feature-Erkennung mit Fallback auf aria-owns
const setOwned = (host, internals, elements) => {
if ('ariaOwnsElements' in ElementInternals.prototype) {
internals.ariaOwnsElements = elements;
} else {
// Fallback: IDs vergeben und Attribut setzen
const ids = elements.map((el) => {
el.id ||= `owned-${crypto.randomUUID()}`;
return el.id;
});
host.setAttribute('aria-owns', ids.join(' '));
}
};
// Wichtig · Fallstricke
- Geltungsbereich: Referenzierte Elemente müssen im selben DOM-Baum wie der Host liegen oder in einem Baum, der ihn über Shadow-Grenzen hinweg umschließt. Elemente im eigenen Shadow Root des Hosts oder in fremden Shadow Roots sind ungültig und werden beim Lesen herausgefiltert.
- Eingefrorenes Array: Methoden wie
push()auf dem gelesenen Wert schlagen fehl oder wirken nicht. Man muss immer ein neues Array zuweisen. - Vorrang: Ein am Host gesetztes
aria-owns-Attribut oderelement.ariaOwnsElementsüberschreibt die Standard-Semantik ausElementInternals. - Sparsam einsetzen:
aria-ownsverändert den Barrierefreiheitsbaum. Wenn möglich, besser die DOM-Struktur passend aufbauen. Ein Element sollte nur einen einzigen Besitzer haben. - Kompatibilität: Die Unterstützung für ARIA-Elementreflexion ist noch jung und uneinheitlich. Vorher per Feature-Erkennung prüfen und gegebenenfalls auf das ID-basierte Attribut ausweichen.