Start · Sprachen · JavaScript · Referenz · new CSSStyleSheet()

new CSSStyleSheet()

Methode

Erzeugt ein neues, eigenständiges <code>CSSStyleSheet</code>-Objekt („Constructable Stylesheet“), das per <code>adoptedStyleSheets</code> an ein Dokument oder einen Shadow Root gehängt werden kann.

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

Signatur

new CSSStyleSheet(options)

Beschreibung

Der Konstruktor CSSStyleSheet() erzeugt ein Stylesheet direkt in JavaScript, ohne dass ein <style>- oder <link>-Element im DOM nötig ist. Solche Stylesheets nennt man Constructable Stylesheets. Man befüllt sie mit replace() (asynchron, liefert ein Promise) oder mit replaceSync() (synchron) und kann einzelne Regeln mit insertRule() bzw. deleteRule() ändern.

Damit das Stylesheet wirkt, muss es über die Eigenschaft adoptedStyleSheets an ein Document oder einen ShadowRoot angehängt werden. Der große Vorteil: Ein einziges Stylesheet-Objekt lässt sich von beliebig vielen Shadow Roots gemeinsam nutzen. Der Browser parst die Regeln nur einmal und hält sie nur einmal im Speicher vor. Bei Web Components mit vielen Instanzen spart das deutlich Arbeit gegenüber einem eigenen <style>-Element pro Instanz.

Ändert man ein geteiltes Stylesheet, zum Beispiel beim Wechsel des Farbschemas, wirkt sich das sofort auf alle Dokumente und Shadow Roots aus, die es übernommen haben. Über das Optionsobjekt lassen sich schon beim Erzeugen Medienabfragen, der Deaktiviert-Zustand und die Basis-URL für relative URLs festlegen.

Parameter

Name Typ Default Beschreibung
$options object {} Optionales Konfigurationsobjekt mit den unten aufgeführten Eigenschaften.
$options.baseURL string URL des Dokuments Basis-URL, gegen die relative URLs im Stylesheet aufgelöst werden, z. B. in url().
$options.media string|MediaList "" Medienabfrage(n), für die das Stylesheet gilt, z. B. "screen and (min-width: 600px)".
$options.disabled boolean false Mit true ist das Stylesheet von Anfang an deaktiviert und wird nicht angewendet.

Rückgabewert

Typ
CSSStyleSheet
Beschreibung
Ein neues, zunächst leeres CSSStyleSheet-Objekt. Die Liste cssRules ist leer, und das Stylesheet gehört noch zu keinem Dokument.

Beispiele

Stylesheet erzeugen und dem Dokument hinzufügen

const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  body { font-family: system-ui, sans-serif; }
  .hinweis { color: darkorange; }
`);

// Bestehende Stylesheets erhalten und das neue anhängen
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

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

Ein Stylesheet von mehreren Web-Component-Instanzen gemeinsam nutzen

// Wird nur einmal geparst, egal wie viele Instanzen es gibt
const buttonStyles = new CSSStyleSheet();
buttonStyles.replaceSync(`
  button { padding: .5rem 1rem; border-radius: 6px; border: none;
           background: rebeccapurple; color: white; }
`);

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

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

Optionen nutzen und Farbschema live umschalten

const darkTheme = new CSSStyleSheet({
  media: 'screen',
  disabled: true // zunächst aus
});

await darkTheme.replace(`
  :root { --bg: #111; --fg: #eee; }
  body { background: var(--bg); color: var(--fg); }
`);

document.adoptedStyleSheets = [...document.adoptedStyleSheets, darkTheme];

const toggleDark = (on) => { darkTheme.disabled = !on; };
toggleDark(true);
console.log(darkTheme.media.mediaText, darkTheme.disabled);
screen false

Feature-Erkennung mit Fallback

const applyCss = (root, css) => {
  if ('adoptedStyleSheets' in Document.prototype && 'replaceSync' in CSSStyleSheet.prototype) {
    const sheet = new CSSStyleSheet();
    sheet.replaceSync(css);
    root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];
  } else {
    // Fallback für ältere Browser
    const style = document.createElement('style');
    style.textContent = css;
    (root === document ? document.head : root).append(style);
  }
};

applyCss(document, 'h1 { letter-spacing: .05em; }');

// Wichtig · Fallstricke

  • @import wird nicht unterstützt: replaceSync() ignoriert @import-Regeln (mit Konsolenwarnung). Bei replace() ist @import ebenfalls nicht erlaubt, und insertRule() mit @import wirft einen SyntaxError.
  • Nur im eigenen Dokument verwendbar: Ein konstruiertes Stylesheet lässt sich nur in dem Dokument (und dessen Shadow Roots) übernehmen, in dem es erzeugt wurde. Ein Stylesheet aus einem anderen Fenster oder iframe führt zu einem NotAllowedError.
  • adoptedStyleSheets war früher unveränderlich: Ältere Browser lieferten ein eingefrorenes Array, und push() schlug fehl. Die portable Lösung ist, jedes Mal ein neues Array zuzuweisen: [...alt, sheet]. Neuere Browser liefern ein veränderbares ObservableArray.
  • Nur für konstruierte Stylesheets: replace() und replaceSync() funktionieren nur bei Stylesheets, die mit diesem Konstruktor erzeugt wurden. Bei Stylesheets aus <style>- oder <link>-Elementen werfen sie einen NotAllowedError.
  • Reihenfolge der Kaskade: Übernommene Stylesheets gelten nach den Stylesheets in document.styleSheets. Bei gleicher Spezifität gewinnen sie also.
  • Sicherheit: Wer CSS aus Nutzereingaben übernimmt, öffnet die Tür für CSS-Injection. Damit lassen sich über Attributselektoren mit url() Daten abgreifen. Eine Content Security Policy mit style-src regelt konstruierte Stylesheets dabei nicht wie Inline-Styles. Fremdes CSS sollte deshalb nie ungeprüft eingesetzt werden.
  • Kompatibilität: Chromium ab Version 73, Firefox ab 101, Safari erst ab 16.4. Für ältere Safari-Versionen braucht man eine Feature-Erkennung mit <style> als Fallback oder ein Polyfill (construct-style-sheets-polyfill).