Start · Sprachen · JavaScript · Referenz · ElementInternals.ariaExpanded

ElementInternals.ariaExpanded

Eigenschaft

Legt für ein Custom Element den Standardwert von <code>aria-expanded</code> fest, also ob ein von ihm gesteuertes Element ein- oder ausgeklappt ist. Im DOM entsteht dabei kein sichtbares Attribut.

seit JavaScript Chrome/Edge 90+, Safari 16.4+, Firefox 119+ Kategorie: webapi

Signatur

ElementInternals.ariaExpanded

Beschreibung

Die Eigenschaft ariaExpanded des ElementInternals-Interfaces spiegelt die ARIA-Eigenschaft aria-expanded wider. Sie teilt Hilfstechnologien wie Screenreadern mit, ob ein Gruppierungselement, das dieses Element besitzt oder steuert, gerade aufgeklappt ("true") oder zugeklappt ("false") ist. Das ist zum Beispiel bei einem Akkordeon-Kopf, einem Menü-Button oder einer Combobox der Fall.

Den Unterschied zu Element.ariaExpanded macht der Ort, an dem der Wert steht: Über ElementInternals legt ein Custom Element seine Standard-Semantik intern fest. Im Light DOM erscheint dabei kein aria-expanded-Attribut. Das Markup bleibt also sauber, und Nutzer der Komponente können den Wert trotzdem mit einem eigenen Attribut am Host-Element überschreiben.

Das ElementInternals-Objekt bekommt man im Konstruktor oder im Lebenszyklus der Komponente über this.attachInternals(). Diese Methode lässt sich pro Element nur einmal aufrufen. Den Rückgabewert speichert man deshalb am besten in einem privaten Feld.

Parameter

Name Typ Default Beschreibung
$wert string | null null Beim Setzen: "true" (aufgeklappt), "false" (zugeklappt), "undefined" (das Element steuert nichts, was sich ein- oder ausklappen lässt) oder null (entfernt den Standardwert).

Rückgabewert

Typ
string | null
Beschreibung
Den aktuell gesetzten Standardwert als Zeichenkette ("true", "false", "undefined") oder null, wenn nichts gesetzt ist.

Beispiele

Aufklappbarer Bereich als Custom Element

class DisclosureToggle extends HTMLElement {
  #internals;

  constructor() {
    super();
    this.#internals = this.attachInternals();
    this.#internals.role = 'button';
    this.#internals.ariaExpanded = 'false';
    this.tabIndex = 0;
    this.addEventListener('click', () => this.toggle());
  }

  toggle() {
    const offen = this.#internals.ariaExpanded === 'true';
    this.#internals.ariaExpanded = String(!offen);
    console.log('ariaExpanded:', this.#internals.ariaExpanded);
  }
}

customElements.define('disclosure-toggle', DisclosureToggle);

const el = document.createElement('disclosure-toggle');
document.body.append(el);
el.click();
ariaExpanded: true

Kein Attribut im DOM sichtbar

class MenuButton extends HTMLElement {
  constructor() {
    super();
    const internals = this.attachInternals();
    internals.role = 'button';
    internals.ariaExpanded = 'false';
    console.log(this.hasAttribute('aria-expanded'), internals.ariaExpanded);
  }
}

customElements.define('menu-button', MenuButton);
document.body.append(document.createElement('menu-button'));
false "false"

Zustand mit einem Popup synchronisieren

class AccordionHeader extends HTMLElement {
  #internals = this.attachInternals();

  connectedCallback() {
    this.#internals.role = 'button';
    const panel = document.getElementById(this.getAttribute('for'));
    const sync = () => {
      this.#internals.ariaExpanded = panel.hidden ? 'false' : 'true';
    };
    sync();
    this.addEventListener('click', () => {
      panel.hidden = !panel.hidden;
      sync();
    });
  }
}

customElements.define('accordion-header', AccordionHeader);

// Wichtig · Fallstricke

  • Nur Zeichenketten: Der Wert wird als String gespeichert. Ein Vergleich wie internals.ariaExpanded === true ist deshalb immer false. Vergleiche besser mit === 'true'.
  • Autoren-Attribute haben Vorrang: Setzt jemand aria-expanded direkt am Host-Element, gilt dieser Wert und nicht der aus ElementInternals.
  • Nur für autonome Custom Elements: attachInternals() löst bei eingebauten Elementen und bei angepassten eingebauten Elementen (is="…") eine NotSupportedError aus.
  • Passende Rolle nötig: aria-expanded ist nur für bestimmte Rollen erlaubt, etwa button, combobox, treeitem oder row. Setze deshalb auch internals.role.
  • Browser-Unterstützung: Die ARIA-Reflexion über ElementInternals gibt es erst seit Firefox 119 und Safari 16.4. Für ältere Browser prüfst du am besten mit 'ariaExpanded' in ElementInternals.prototype und setzt als Ausweichlösung das Attribut.