Start · Sprachen · JavaScript · Referenz · ShadowRoot.activeElement

ShadowRoot.activeElement

Eigenschaft

Gibt das Element innerhalb des Schattenbaums zurück, das gerade den Fokus hat, oder <code>null</code>, wenn kein Element darin fokussiert ist.

seit JavaScript Baseline: alle modernen Browser (seit ca. 2020) Kategorie: webapi

Signatur

ShadowRoot.activeElement

Beschreibung

Die schreibgeschützte Eigenschaft activeElement eines ShadowRoot liefert das Element innerhalb des Schattenbaums, das aktuell den Tastatur-Fokus besitzt. Sie ist das Gegenstück zu document.activeElement, wirkt aber nur auf den jeweiligen Shadow DOM.

Wegen der Kapselung (Retargeting) meldet document.activeElement bei einem fokussierten Element im Shadow DOM nur den Host der Web Component, also z. B. <my-input>, und nicht das eigentliche <input> darin. Um das tatsächlich fokussierte innere Element zu finden, fragt man shadowRoot.activeElement ab. Bei verschachtelten Komponenten muss man sich rekursiv durch die Schattenbäume nach unten arbeiten.

Typische Anwendungsfälle sind Fokusverwaltung in Web Components (Tastaturnavigation, Roving Tabindex, Fokusfallen in Dialogen), Barrierefreiheit und das Wiederherstellen des Fokus nach einem Neurendern.

Liegt der Fokus außerhalb dieses Schattenbaums, ist der Wert null. Befindet sich das fokussierte Element in einem verschachtelten Schattenbaum, liefert die Eigenschaft den Host dieses inneren Baums, der im aktuellen Baum liegt.

Rückgabewert

Typ
Element | null
Beschreibung
Das fokussierte Element im Schattenbaum (bzw. der Host eines verschachtelten Schattenbaums, der den Fokus enthält) oder null, wenn der Fokus nicht in diesem Schattenbaum liegt.

Beispiele

Fokussiertes Element innerhalb einer Web Component ermitteln

class LoginForm extends HTMLElement {
  constructor() {
    super();
    const root = this.attachShadow({ mode: 'open' });
    root.innerHTML = `
      <input id="user" placeholder="Benutzer">
      <input id="pass" type="password" placeholder="Passwort">
    `;
  }
}
customElements.define('login-form', LoginForm);

const form = document.createElement('login-form');
document.body.append(form);
form.shadowRoot.querySelector('#pass').focus();

console.log(document.activeElement.tagName);      // Host
console.log(form.shadowRoot.activeElement.id);    // tatsächliches Element
LOGIN-FORM pass

Tief verschachtelten Fokus rekursiv auflösen

// Liefert das wirklich fokussierte Element über alle Shadow-Grenzen hinweg
const getDeepActiveElement = (root = document) => {
  let active = root.activeElement;
  while (active?.shadowRoot?.activeElement) {
    active = active.shadowRoot.activeElement;
  }
  return active;
};

document.addEventListener('focusin', () => {
  const el = getDeepActiveElement();
  console.log('Fokus auf:', el?.tagName, el?.id);
});
Fokus auf: INPUT pass

Fokus nach Neurendern wiederherstellen

class TodoList extends HTMLElement {
  #root = this.attachShadow({ mode: 'open' });
  items = ['Einkaufen', 'Putzen'];

  connectedCallback() { this.render(); }

  render() {
    // ID des fokussierten Elements merken
    const focusedId = this.#root.activeElement?.id;
    this.#root.innerHTML = this.items
      .map((t, i) => `<button id="item-${i}">${t}</button>`)
      .join('');
    if (focusedId) this.#root.getElementById(focusedId)?.focus();
  }
}
customElements.define('todo-list', TodoList);

Prüfen, ob der Fokus in der Komponente liegt

const dialog = document.querySelector('my-dialog');
const hasFocusInside = dialog.shadowRoot.activeElement !== null;
console.log(hasFocusInside ? 'Fokus im Dialog' : 'Fokus außerhalb');
Fokus außerhalb

// Wichtig · Fallstricke

  • Retargeting: document.activeElement liefert nur den Shadow-Host. Für das echte Element immer shadowRoot.activeElement verwenden – bei verschachtelten Komponenten rekursiv.
  • Geschlossene Schattenbäume: Bei mode: 'closed' ist element.shadowRoot null. Nur die Komponente selbst kann über die bei attachShadow() gespeicherte Referenz auf activeElement zugreifen.
  • Der Wert ist null (nicht body wie bei document.activeElement), wenn kein Element im Schattenbaum fokussiert ist.
  • Die Eigenschaft ist schreibgeschützt; zum Fokussieren element.focus() verwenden. Mit delegatesFocus: true in attachShadow() wird der Fokus beim Klick auf den Host automatisch an das erste fokussierbare innere Element weitergereicht.
  • Die CSS-Pseudoklasse :focus-within auf dem Host ist oft eine einfachere Alternative, wenn nur das Styling angepasst werden soll.
  • Kompatibilität: in Chrome, Edge, Firefox und Safari unterstützt; die Eigenschaft ist in der Spezifikation über das Mixin DocumentOrShadowRoot definiert.