Signatur
Beschreibung
Die Eigenschaft role der Schnittstelle ElementInternals gehört zum Mechanismus ARIA-Reflexion über ElementInternals. Damit legt ein autonomes Custom Element (Web Component) seine Standardrolle für den Barrierefreiheitsbaum fest, zum Beispiel "button", "checkbox" oder "tablist". Screenreader und andere Hilfstechnologien sehen das Element dann mit dieser Rolle.
Der entscheidende Unterschied zum Attribut role bzw. zu Element.role: Der über ElementInternals gesetzte Wert ist ein interner Standardwert. Er taucht nicht als Attribut im Markup auf, und Nutzer der Komponente können ihn jederzeit mit einem eigenen role-Attribut am Host-Element überschreiben. So verhält sich die Komponente wie ein natives HTML-Element, das ebenfalls eine implizite Rolle hat (etwa <button>).
Typischerweise setzt man die Eigenschaft einmal im Konstruktor der Komponente, direkt nach this.attachInternals(). Dazu passende Zustände wie ariaChecked, ariaPressed oder ariaDisabled setzt man ebenfalls über das ElementInternals-Objekt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value | string | null | null | Beim Schreiben: eine gültige WAI-ARIA-Rolle wie "button", "switch" oder "listbox". Mit null entfernen Sie die Standardrolle wieder. |
Rückgabewert
null, wenn keine gesetzt ist. Der Wert wird so zurückgegeben, wie er gesetzt wurde. Es findet keine Prüfung auf eine gültige Rolle statt.Beispiele
Standardrolle im Konstruktor setzen
class FancyButton extends HTMLElement {
constructor() {
super();
this.internals = this.attachInternals();
// Implizite Rolle wie bei einem nativen <button>
this.internals.role = 'button';
this.tabIndex = 0;
}
}
customElements.define('fancy-button', FancyButton);
const btn = document.createElement('fancy-button');
document.body.append(btn);
console.log(btn.internals.role);
console.log(btn.getAttribute('role'));
Schalter mit Rolle und ARIA-Zustand
class ToggleSwitch extends HTMLElement {
#internals;
#on = false;
constructor() {
super();
this.#internals = this.attachInternals();
this.#internals.role = 'switch';
this.#internals.ariaChecked = 'false';
this.tabIndex = 0;
this.addEventListener('click', () => this.toggle());
this.addEventListener('keydown', (e) => {
if (e.key === ' ' || e.key === 'Enter') {
e.preventDefault();
this.toggle();
}
});
}
toggle() {
this.#on = !this.#on;
this.#internals.ariaChecked = String(this.#on);
console.log(`Zustand: ${this.#internals.ariaChecked}`);
}
}
customElements.define('toggle-switch', ToggleSwitch);
const sw = document.createElement('toggle-switch');
document.body.append(sw);
sw.click();
Autor überschreibt die Standardrolle per Attribut
class InfoCard extends HTMLElement {
constructor() {
super();
this.internals = this.attachInternals();
this.internals.role = 'region';
}
}
customElements.define('info-card', InfoCard);
document.body.innerHTML = '<info-card role="note"></info-card>';
const card = document.querySelector('info-card');
// Interner Standardwert bleibt erhalten,
// Hilfstechnologien verwenden aber das Attribut "note"
console.log(card.internals.role, card.getAttribute('role'));
Feature-Erkennung mit Fallback
class MyTab extends HTMLElement {
constructor() {
super();
const internals = this.attachInternals?.();
if (internals && 'role' in internals) {
internals.role = 'tab';
} else if (!this.hasAttribute('role')) {
// Fallback für ältere Browser: sichtbares Attribut
this.setAttribute('role', 'tab');
}
}
}
customElements.define('my-tab', MyTab);
// Wichtig · Fallstricke
- Nur für Custom Elements:
attachInternals()funktioniert nur bei autonomen Custom Elements. Bei eingebauten Elementen und bei angepassten eingebauten Elementen (is="…") wirft der Aufruf einenNotSupportedError. Außerdem lässt er sich pro Element nur einmal ausführen. - Keine Prüfung: Ungültige oder abstrakte Rollen (z. B.
"widget") werden ohne Fehler gespeichert, aber von Hilfstechnologien ignoriert. Nutzen Sie nur konkrete Rollen aus der WAI-ARIA-Spezifikation. - Die Rolle ersetzt kein Verhalten: Wer
role = 'button'setzt, muss Fokussierbarkeit (tabIndex) und Tastaturbedienung (Enter/Leertaste) selbst umsetzen. - Vorrang des Attributs: Ein
role-Attribut am Host-Element hat immer Vorrang vor dem internen Wert. Das ist so gewollt und sollte nicht umgangen werden. - Nicht in CSS-Selektoren sichtbar: Da kein Attribut entsteht, greift
[role="button"]nicht. Für das Styling bieten sich:hostoder benutzerdefinierte Zustände (internals.states,:state()) an. - Kompatibilität: Firefox unterstützt die ARIA-Eigenschaften an
ElementInternalserst ab Version 119. Für ältere Browser brauchen Sie eine Feature-Erkennung ('role' in internals) mit einem Attribut als Fallback.