Signatur
Beschreibung
Die Eigenschaft ariaLabelledByElements des ElementInternals-Interfaces legt fest, welche Elemente einem autonomen Custom Element seinen zugänglichen Namen (accessible name) geben. Sie ist die Entsprechung des Attributs aria-labelledby. Statt einer Liste von IDs als Zeichenkette übergibt man hier direkt Element-Referenzen. Diesen Mechanismus nennt man ARIA-Element-Reflexion.
Die Werte in ElementInternals gelten als Standard-Semantik der Komponente. Sie tauchen nicht als Attribut im DOM auf und werden vom Browser nur genutzt, wenn der Anwender auf dem Host-Element selbst weder aria-labelledby noch ariaLabelledByElements setzt. So kann eine Komponente ihre Beschriftung selbst bestimmen, und Nutzer der Komponente können sie trotzdem überschreiben.
Den Zugriff auf das ElementInternals-Objekt bekommt man über this.attachInternals() im Konstruktor des Custom Elements. Der Browser setzt die Texte der referenzierten Elemente in der angegebenen Reihenfolge und mit Leerzeichen getrennt zum zugänglichen Namen zusammen.
Die Eigenschaft passt, wenn schon sichtbarer Text vorhanden ist, der das Element beschreibt, etwa eine Überschrift oder ein Label-Element. Gibt es keinen solchen Text, ist ariaLabel meist die einfachere Wahl.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value | Array<Element> | null | null | Neuer Wert beim Setzen: ein Array von Elementen, die das Element beschriften. Mit null entfernt man die Standard-Beschriftung. |
Rückgabewert
null, wenn nichts gesetzt ist. Elemente, die die Scope-Regeln verletzen (siehe Hinweise), fehlen im Array.Beispiele
Custom Element mit externer Beschriftung
// HTML: <h2 id="titel">Lautstärke</h2> <volume-knob></volume-knob>
class VolumeKnob extends HTMLElement {
#internals;
constructor() {
super();
this.#internals = this.attachInternals();
this.#internals.role = 'slider';
this.#internals.ariaValueMin = '0';
this.#internals.ariaValueMax = '100';
this.#internals.ariaValueNow = '50';
}
connectedCallback() {
// Die Überschrift vor der Komponente liefert den zugänglichen Namen
const heading = document.getElementById('titel');
if (heading) {
this.#internals.ariaLabelledByElements = [heading];
}
console.log(this.#internals.ariaLabelledByElements.map((el) => el.id));
}
}
customElements.define('volume-knob', VolumeKnob);
Mehrere Elemente kombinieren und die Beschriftung entfernen
class InfoCard extends HTMLElement {
internals = this.attachInternals();
connectedCallback() {
this.internals.role = 'region';
const prefix = document.querySelector('#bereich'); // z. B. "Kontakt"
const name = document.querySelector('#kartenname'); // z. B. "Max Muster"
// Reihenfolge im Array = Reihenfolge im zugänglichen Namen
this.internals.ariaLabelledByElements = [prefix, name];
}
clearLabel() {
this.internals.ariaLabelledByElements = null;
console.log(this.internals.ariaLabelledByElements);
}
}
customElements.define('info-card', InfoCard);
// Zugänglicher Name z. B.: "Kontakt Max Muster"
document.querySelector('info-card')?.clearLabel();
Feature-Erkennung mit Fallback auf das Attribut
const supportsReflection = 'ariaLabelledByElements' in ElementInternals.prototype;
class FancyInput extends HTMLElement {
#internals = this.attachInternals();
setLabel(labelEl) {
if (supportsReflection) {
this.#internals.ariaLabelledByElements = [labelEl];
} else if (labelEl.id) {
// Fallback: klassisches ID-basiertes Attribut auf dem Host
this.setAttribute('aria-labelledby', labelEl.id);
}
}
}
customElements.define('fancy-input', FancyInput);
console.log(supportsReflection);
// Wichtig · Fallstricke
- Das Array ist eingefroren: Aufrufe wie
internals.ariaLabelledByElements.push(el)werfen einen Fehler oder wirken nicht. Weisen Sie immer ein neues Array zu, z. B.internals.ariaLabelledByElements = [...alt, el]. - Scope-Regeln: Die referenzierten Elemente müssen im selben DOM-Baum liegen wie das Element oder in einem Baum darüber (einem Shadow-inklusiven Vorfahren). Andere Referenzen über Shadow-DOM-Grenzen hinweg sind eingeschränkt. Ungültige Elemente lässt der Getter weg. Prüfen Sie das Verhalten in allen Zielbrowsern, besonders wenn Sie auf Elemente im eigenen Shadow Root verweisen.
- Kein Attribut im DOM: Werte in
ElementInternalserzeugen keinaria-labelledby-Attribut. Setzt der Anwender auf dem Hostaria-labelledbyoderelement.ariaLabelledByElements, hat das Vorrang. - Keine Speicherlecks: Der Browser hält die Referenzen nicht fest (sie sind schwach). Wird ein beschriftendes Element aus dem DOM entfernt, fällt es aus der Berechnung des Namens heraus.
- Kompatibilität: Die Unterstützung ist relativ neu. Ältere Browser kennen die Eigenschaft nicht, eine Zuweisung legt dann nur eine normale JS-Eigenschaft ohne Wirkung an. Nutzen Sie Feature-Erkennung (
'ariaLabelledByElements' in ElementInternals.prototype) und testen Sie mit echten Screenreadern. - Nur autonome Custom Elements können
attachInternals()aufrufen. Bei eingebauten Elementen wie<button>wirft der Aufruf einenNotSupportedError.