Signatur
Beschreibung
Über ElementInternals.ariaChecked legt ein autonomes Custom Element (Web Component) seine Standard-Semantik für den ARIA-Zustand aria-checked fest. Der Zustand gehört zu Widgets, die man an- oder abwählen kann, zum Beispiel role="checkbox", role="radio", role="switch" oder role="menuitemcheckbox". Screenreader lesen den Wert vor, etwa „Kontrollkästchen, aktiviert“.
Der große Unterschied zu Element.ariaChecked oder setAttribute('aria-checked', …): Ein Wert, den man über ElementInternals setzt, erscheint nicht als Attribut im DOM des Host-Elements. Das Markup bleibt sauber, und die Komponente verwaltet ihren Zustand intern. Setzt ein Autor das Attribut aria-checked direkt am Element, überschreibt dieses Attribut den internen Standardwert.
Die Eigenschaft nimmt einen String an: "true", "false", "mixed" (unbestimmt, nur bei Checkboxen sinnvoll) oder "undefined". Mit null entfernt man den Standardwert. Das ElementInternals-Objekt bekommt man über this.attachInternals(), normalerweise im Konstruktor der Custom-Element-Klasse.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value (Setter) | string | null | null | Neuer Zustand: "true", "false", "mixed" oder "undefined". Mit null wird der Standardwert entfernt. |
Rückgabewert
"true"). Wurde nichts gesetzt, ist der Wert null. Nicht-Strings wandelt der Setter in Strings um.Beispiele
Barrierefreie Custom-Checkbox
class FancyCheckbox extends HTMLElement {
#internals;
#checked = false;
constructor() {
super();
this.#internals = this.attachInternals();
this.#internals.role = 'checkbox';
this.#internals.ariaChecked = 'false';
}
connectedCallback() {
if (!this.hasAttribute('tabindex')) this.tabIndex = 0;
this.addEventListener('click', () => this.toggle());
this.addEventListener('keydown', (e) => {
if (e.key === ' ') {
e.preventDefault();
this.toggle();
}
});
}
toggle() {
this.#checked = !this.#checked;
this.#internals.ariaChecked = String(this.#checked);
this.#internals.states.add?.('checked');
if (!this.#checked) this.#internals.states.delete?.('checked');
}
get checked() { return this.#checked; }
}
customElements.define('fancy-checkbox', FancyCheckbox);
const box = document.createElement('fancy-checkbox');
document.body.append(box);
box.click();
console.log(box.checked, box.getAttribute('aria-checked'));
Dreifach-Zustand „mixed“ für eine „Alle auswählen“-Checkbox
class SelectAll extends HTMLElement {
static observedAttributes = ['selected', 'total'];
#internals = this.attachInternals();
constructor() {
super();
this.#internals.role = 'checkbox';
this.#internals.ariaLabel = 'Alle auswählen';
}
attributeChangedCallback() {
const selected = Number(this.getAttribute('selected') ?? 0);
const total = Number(this.getAttribute('total') ?? 0);
this.#internals.ariaChecked =
selected === 0 ? 'false' : selected === total ? 'true' : 'mixed';
}
get state() { return this.#internals.ariaChecked; }
}
customElements.define('select-all', SelectAll);
const el = document.createElement('select-all');
el.setAttribute('total', '5');
el.setAttribute('selected', '2');
console.log(el.state);
Autor-Attribut überschreibt den internen Standardwert
class ToggleSwitch extends HTMLElement {
internals = this.attachInternals();
constructor() {
super();
this.internals.role = 'switch';
this.internals.ariaChecked = 'false';
}
}
customElements.define('toggle-switch', ToggleSwitch);
const sw = document.createElement('toggle-switch');
// Das Attribut am Host hat Vorrang vor ElementInternals:
sw.setAttribute('aria-checked', 'true');
console.log(sw.internals.ariaChecked); // interner Standardwert
console.log(sw.ariaChecked); // gespiegeltes Attribut
// Wichtig · Fallstricke
- Nur für autonome Custom Elements:
attachInternals()funktioniert nicht bei eingebauten Elementen wie<div>und nicht bei „customized built-ins“ (is="…"). Sonst gibt es einenNotSupportedError. Pro Element darf man es nur einmal aufrufen. - Die Rolle ist Pflicht:
ariaCheckedwirkt nur bei einer passenden Rolle, zum Beispielinternals.role = 'checkbox'. Ohne Rolle ignorieren Screenreader den Wert. - Kein Attribut im DOM: Der Wert erscheint nicht als
aria-checkedam Host. CSS-Selektoren wie[aria-checked="true"]treffen deshalb nicht. Für das Styling eignen sich benutzerdefinierte Zustände überinternals.statesund:state(checked). - Nur Strings:
internals.ariaChecked = truewird zu"true". Das klappt, aberString(value)ist klarer. Unbekannte Werte wie"yes"werden gespeichert, sind aber ungültiges ARIA. - Tastatur und Fokus fehlen: ARIA beschreibt nur den Zustand. Fokussierbarkeit (
tabIndex) und Tastaturbedienung (Leertaste) muss die Komponente selbst umsetzen. - Kompatibilität: Die ARIA-Reflexion auf
ElementInternalsgibt es erst ab Chrome 81, Safari 16.4 und Firefox 119. Wer ältere Browser unterstützen muss, prüft vorher mit'ariaChecked' in ElementInternals.prototypeund greift sonst aufsetAttributezurück.