Signatur
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
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);
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);
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();
// Wichtig · Fallstricke
- Nur konstruierte Stylesheets: Stylesheets aus
document.styleSheetsoder aus<style>-Elementen sind nicht erlaubt. Versucht man es trotzdem, wirft der Browser einenNotAllowedError(DOMException). Das gilt auch für Stylesheets, die in einem anderen Dokument erzeugt wurden, etwa in einem<iframe>. @importwird nicht unterstützt: InreplaceSync()werden@import-Regeln ignoriert, undreplace()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-polyfilloder als Ersatz ein<style>-Element. Array-Methoden wiepush()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.