Start · Sprachen · JavaScript · Referenz · ShadowRoot.adoptedStyleSheets

ShadowRoot.adoptedStyleSheets

Eigenschaft

Liest oder setzt ein Array von <code>CSSStyleSheet</code>-Objekten (Constructable Stylesheets), die zusätzlich auf den Shadow-DOM-Teilbaum angewendet werden.

seit JavaScript Baseline 2023: Chrome 73+, Edge 79+, Firefox 101+, Kategorie: webapi

Signatur

ShadowRoot.adoptedStyleSheets

Beschreibung

Über adoptedStyleSheets kann man einem Shadow Root Stylesheets zuweisen, die per new CSSStyleSheet() erzeugt wurden (sogenannte Constructable Stylesheets). Diese Stylesheets gelten nur innerhalb des jeweiligen Shadow-Teilbaums. Sie werden zusätzlich zu den <style>- und <link rel="stylesheet">-Elementen im Shadow Root angewendet, und zwar nach diesen, also mit höherer Priorität in der Kaskade.

Der größte Vorteil: Ein einzelnes CSSStyleSheet-Objekt lässt sich von beliebig vielen Shadow Roots (und über document.adoptedStyleSheets auch vom Dokument) gemeinsam nutzen. Der Browser parst das CSS nur einmal und hält es nur einmal im Speicher. Ändert man das Stylesheet, zum Beispiel mit replaceSync() oder insertRule(), wirkt sich das sofort auf alle Stellen aus, die es übernommen haben. Deshalb eignet sich die Eigenschaft besonders für Web Components, Design-Systeme und Themes.

Der Wert ist ein ObservableArray. In aktuellen Browsern kann man ihn wie ein normales Array verändern, etwa mit push() oder splice(). Man kann ihm aber auch ein komplett neues Array zuweisen. Erlaubt sind nur CSSStyleSheet-Instanzen, die mit dem Konstruktor erzeugt wurden und zum selben Document gehören wie der Shadow Root.

Parameter

Name Typ Default Beschreibung
$wert (bei Zuweisung) Array<CSSStyleSheet> [] Array mit per new CSSStyleSheet() erzeugten Stylesheets. Die Reihenfolge entspricht der Reihenfolge in der Kaskade: Spätere Einträge überschreiben frühere.

Rückgabewert

Typ
ObservableArray<CSSStyleSheet>
Beschreibung
Das aktuelle, veränderbare Array der übernommenen Stylesheets dieses Shadow Roots. Anfangs ist es leer.

Beispiele

Web Component mit gemeinsam genutztem Stylesheet

// Einmal erzeugen, in allen Instanzen wiederverwenden
const buttonStyles = new CSSStyleSheet();
buttonStyles.replaceSync(`
  :host { display: inline-block; }
  button { padding: .5rem 1rem; border-radius: 6px; background: rebeccapurple; color: white; }
`);

class FancyButton extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    shadow.adoptedStyleSheets = [buttonStyles];
    shadow.innerHTML = '<button><slot></slot></button>';
  }
}

customElements.define('fancy-button', FancyButton);
document.body.insertAdjacentHTML('beforeend', '<fancy-button>OK</fancy-button><fancy-button>Abbrechen</fancy-button>');

console.log(document.querySelector('fancy-button').shadowRoot.adoptedStyleSheets.length);
1

Stylesheet ergänzen, ohne bestehende zu verlieren

const host = document.createElement('div');
document.body.append(host);
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = '<p>Hallo Shadow DOM</p>';

const base = new CSSStyleSheet();
base.replaceSync('p { font-family: sans-serif; }');
shadow.adoptedStyleSheets = [base];

const highlight = new CSSStyleSheet();
highlight.replaceSync('p { color: crimson; }');

// Moderne Browser: direkt push(); kompatibel: neues Array zuweisen
shadow.adoptedStyleSheets = [...shadow.adoptedStyleSheets, highlight];

console.log(shadow.adoptedStyleSheets.length);
2

Theme zur Laufzeit für alle Komponenten umschalten

const theme = new CSSStyleSheet();
theme.replaceSync(':host { --accent: steelblue; }');

const hosts = [1, 2, 3].map(() => {
  const el = document.createElement('div');
  const shadow = el.attachShadow({ mode: 'open' });
  shadow.adoptedStyleSheets = [theme];
  shadow.innerHTML = '<span style="color: var(--accent)">Text</span>';
  document.body.append(el);
  return el;
});

// Eine Änderung wirkt sofort in allen drei Shadow Roots
const setDarkTheme = async () => {
  await theme.replace(':host { --accent: orange; }');
  console.log('Theme aktualisiert für', hosts.length, 'Komponenten');
};
setDarkTheme();
Theme aktualisiert für 3 Komponenten

// Wichtig · Fallstricke

  • Nur konstruierte Stylesheets: Stylesheets aus document.styleSheets oder aus <style>-Elementen sind nicht erlaubt. Versucht man es trotzdem, wirft der Browser einen NotAllowedError (DOMException). Das gilt auch für Stylesheets, die in einem anderen Dokument erzeugt wurden, etwa in einem <iframe>.
  • @import wird nicht unterstützt: In replaceSync() werden @import-Regeln ignoriert, und replace() lehnt sie ab.
  • Kompatibilität: Safari unterstützt die Eigenschaft erst ab Version 16.4, Firefox ab Version 101. Ältere Browser brauchen ein Polyfill wie construct-style-sheets-polyfill oder als Ersatz ein <style>-Element. Array-Methoden wie push() auf dem ObservableArray funktionieren erst in neueren Versionen (etwa Chrome 99+). Am sichersten ist es, ein neues Array zuzuweisen.
  • Nicht versehentlich überschreiben: Mit shadow.adoptedStyleSheets = [neu] werden alle bisherigen Einträge entfernt. Wer ergänzen will, verwendet den Spread-Operator.
  • Kaskade: Übernommene Stylesheets werden nach den Stylesheets im Baum angewendet. Bei gleicher Spezifität gewinnen sie deshalb gegenüber <style>-Elementen im Shadow Root.
  • Deklaratives Shadow DOM: Mit <template shadowrootmode> kann man übernommene Stylesheets nicht direkt im HTML angeben. Man setzt sie danach per Skript.