Start · Sprachen · JavaScript · Referenz · CSSStyleSheet.replace()

CSSStyleSheet.replace()

Methode

Ersetzt asynchron den gesamten Inhalt eines konstruierten Stylesheets durch den übergebenen CSS-Text und gibt ein <code>Promise</code> zurück, das mit dem Stylesheet erfüllt wird.

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

Signatur

CSSStyleSheet.prototype.replace(text)

Beschreibung

replace() ersetzt alle Regeln eines konstruierten Stylesheets, also eines mit new CSSStyleSheet() erzeugten Stylesheets, durch neuen CSS-Text. Die Methode arbeitet asynchron und gibt ein Promise zurück. Es wird erfüllt, sobald der Text geparst und die Regeln übernommen wurden.

Typische Einsatzfälle sind Constructable Stylesheets für Web Components und Themes. Ein einziges Stylesheet-Objekt kann über document.adoptedStyleSheets oder shadowRoot.adoptedStyleSheets in mehreren Dokumenten oder Shadow Roots gleichzeitig verwendet werden. Ändert man es mit replace(), wirkt sich das sofort auf alle Stellen aus, die es übernommen haben. Man muss keine <style>-Elemente duplizieren.

Der Unterschied zu replaceSync(): Beide ignorieren @import-Regeln, weil diese in konstruierten Stylesheets nicht erlaubt sind. replace() gibt aber ein Promise zurück und blockiert den Hauptthread nicht. Das ist praktisch, wenn der CSS-Text ohnehin asynchron geladen wird, zum Beispiel per fetch(). Für kleine, fest im Code stehende Styles reicht in der Regel replaceSync().

Parameter

Name Typ Default Beschreibung
$text Pflicht string CSS-Text, der den bisherigen Inhalt komplett ersetzt. Enthaltene @import-Regeln werden ignoriert (mit Konsolenwarnung). Ungültige Regeln werden wie üblich stillschweigend verworfen.

Rückgabewert

Typ
Promise<CSSStyleSheet>
Beschreibung
Ein Promise, das mit demselben CSSStyleSheet-Objekt erfüllt wird, sobald der neue Inhalt übernommen ist. Es wird mit einem NotAllowedError (DOMException) abgelehnt, wenn das Stylesheet nicht konstruiert wurde (z. B. aus einem <style>- oder <link>-Element stammt) oder gerade durch einen anderen replace()-Aufruf verändert wird.

Beispiele

Konstruiertes Stylesheet erzeugen und dem Dokument zuweisen

const sheet = new CSSStyleSheet();

await sheet.replace(`
  body { font-family: system-ui, sans-serif; }
  .hinweis { color: white; background: rebeccapurple; padding: .5rem; }
`);

// Stylesheet zusätzlich zu bestehenden übernehmen
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

console.log(sheet.cssRules.length);
2

Gemeinsames Stylesheet für Web Components

const sharedSheet = new CSSStyleSheet();
sharedSheet.replace(':host { display: block; border: 1px solid #ccc; padding: 1rem; }');

class InfoBox extends HTMLElement {
  constructor() {
    super();
    const root = this.attachShadow({ mode: 'open' });
    root.adoptedStyleSheets = [sharedSheet];
    root.innerHTML = '<slot></slot>';
  }
}
customElements.define('info-box', InfoBox);

// Spätere Änderung wirkt auf ALLE <info-box>-Instanzen
setTimeout(async () => {
  await sharedSheet.replace(':host { display: block; border: 2px solid tomato; padding: 1rem; }');
  console.log('Theme aktualisiert');
}, 2000);
Theme aktualisiert

Theme per fetch laden und austauschen

const themeSheet = new CSSStyleSheet();
document.adoptedStyleSheets = [...document.adoptedStyleSheets, themeSheet];

const ladeTheme = async (name) => {
  const res = await fetch(`/themes/${name}.css`);
  if (!res.ok) throw new Error(`Theme ${name} nicht gefunden`);
  const css = await res.text();
  try {
    await themeSheet.replace(css);
    console.log(`Theme "${name}" aktiv, ${themeSheet.cssRules.length} Regeln`);
  } catch (err) {
    console.error('replace() fehlgeschlagen:', err.name);
  }
};

ladeTheme('dunkel');
Theme "dunkel" aktiv, 42 Regeln

Fehlerfall: nicht konstruiertes Stylesheet

const style = document.createElement('style');
style.textContent = 'p { color: red; }';
document.head.append(style);

try {
  await style.sheet.replace('p { color: blue; }');
} catch (err) {
  console.log(err.name);
}
NotAllowedError

// Wichtig · Fallstricke

  • Nur für konstruierte Stylesheets: Bei Stylesheets aus <style> oder <link> wird das Promise mit NotAllowedError abgelehnt. Dort ändert man den Inhalt über textContent, insertRule() oder deleteRule().
  • @import wird ignoriert: Externe Stylesheets müssen separat geladen werden, zum Beispiel per fetch(). Alternativ legt man ein eigenes CSSStyleSheet an.
  • Parallele Aufrufe: Ein zweiter replace()-Aufruf, solange der erste noch läuft, kann abgelehnt werden. Deshalb Aufrufe mit await nacheinander ausführen.
  • Vollständiger Austausch: Alle bisherigen Regeln gehen verloren, auch solche, die mit insertRule() hinzugefügt wurden.
  • Sicherheit: CSS aus nicht vertrauenswürdigen Quellen kann Daten abgreifen (etwa über Attribut-Selektoren mit url()) oder die Oberfläche manipulieren. Solches CSS nicht ungeprüft übergeben. Eine passende CSP (style-src, img-src) begrenzt das Risiko.
  • Kompatibilität: Constructable Stylesheets sind erst seit 2023 in allen großen Browsern verfügbar, in Safari ab 16.4. Für ältere Browser vorher prüfen, zum Beispiel mit 'replace' in CSSStyleSheet.prototype, und sonst auf <style>-Elemente ausweichen.