Start · Sprachen · JavaScript · Referenz · CSSNestedDeclarations

CSSNestedDeclarations

Schnittstelle

Steht im CSSOM für einen Block einfacher Deklarationen, die innerhalb einer verschachtelten Regel <em>nach</em> oder zwischen verschachtelten Regeln stehen. So bleibt ihre Reihenfolge erhalten.

seit JavaScript Baseline 2024: Chrome/Edge 130+, Firefox 132+, Saf Kategorie: webapi

Signatur

interface CSSNestedDeclarations extends CSSRule

Beschreibung

Das Interface CSSNestedDeclarations gehört zum CSS Object Model (CSSOM) und wurde mit CSS Nesting eingeführt. Es steht für eine Gruppe normaler Eigenschafts-Deklarationen (z. B. color: red;), die innerhalb einer Stilregel nicht am Anfang stehen, sondern auf verschachtelte Regeln wie @media, &:hover oder .child { … } folgen. Solche Deklarationen landen nicht in der style-Eigenschaft der übergeordneten CSSStyleRule. Stattdessen erscheinen sie als eigenes CSSNestedDeclarations-Objekt in deren cssRules-Liste.

Wozu das gut ist: Früher hat der Browser Deklarationen nach verschachtelten Regeln stillschweigend an den Anfang der Regel „hochgezogen“. Dadurch ließ sich z. B. eine Eigenschaft in einer Media-Query nicht zuverlässig danach überschreiben. Mit CSSNestedDeclarations behält der Browser die Reihenfolge aus dem Quelltext bei, und die Kaskade verhält sich so, wie man es beim Lesen des CSS erwartet. Auch einfache Deklarationen direkt in einer verschachtelten @media- oder @supports-Regel werden als CSSNestedDeclarations dargestellt.

Das Interface erbt von CSSRule (also cssText, parentRule, parentStyleSheet usw.). Eine eigene Eigenschaft kommt hinzu:

  • style (nur lesbar): ein CSSStyleDeclaration-Objekt (in neueren Spezifikationen CSSStyleProperties). Über dieses Objekt liest und änderst du die Deklarationen des Blocks.

Es gibt keinen öffentlichen Konstruktor. Solche Objekte entstehen nur, wenn der Browser verschachteltes CSS parst, etwa aus einem <style>-Element, über CSSStyleSheet.replaceSync() oder mit insertRule().

Rückgabewert

Typ
CSSNestedDeclarations
Beschreibung
Diese Objekte erstellst du nicht selbst. Du findest sie in CSSStyleRule.cssRules oder in den cssRules verschachtelter Gruppierungsregeln. Über style greifst du auf die Deklarationen zu.

Beispiele

Verschachtelte Deklarationen im CSSOM finden

const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  .card {
    color: black;
    @media (min-width: 600px) {
      padding: 2rem;
    }
    background: white;
  }
`);

const card = sheet.cssRules[0]; // CSSStyleRule
console.log(card.style.cssText);            // nur Deklarationen VOR den verschachtelten Regeln
console.log(card.cssRules.length);

for (const rule of card.cssRules) {
  console.log(rule.constructor.name);
}

const trailing = card.cssRules[1];
console.log(trailing instanceof CSSNestedDeclarations);
console.log(trailing.style.background);
color: black; 2 CSSMediaRule CSSNestedDeclarations true white

Deklarationen innerhalb einer verschachtelten @media-Regel ändern

const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  .btn {
    font-size: 1rem;
    @media (prefers-reduced-motion: no-preference) {
      transition: transform 0.2s;
    }
  }
`);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

const media = sheet.cssRules[0].cssRules[0];       // CSSMediaRule
const decls = media.cssRules[0];                    // CSSNestedDeclarations

// Übergangsdauer zur Laufzeit anpassen
decls.style.setProperty('transition', 'transform 0.5s ease-out');
console.log(decls.cssText);
transition: transform 0.5s ease-out;

Feature-Erkennung und rekursives Auslesen aller Deklarationen

const supportsNestedDecls = typeof CSSNestedDeclarations !== 'undefined';
console.log('CSSNestedDeclarations unterstützt:', supportsNestedDecls);

// Alle Deklarationsblöcke eines Stylesheets rekursiv sammeln
const collectDeclarations = (rules, out = []) => {
  for (const rule of rules) {
    if (rule instanceof CSSStyleRule) {
      out.push({ selector: rule.selectorText, css: rule.style.cssText });
    } else if (supportsNestedDecls && rule instanceof CSSNestedDeclarations) {
      out.push({ selector: '(verschachtelt)', css: rule.style.cssText });
    }
    if (rule.cssRules) collectDeclarations(rule.cssRules, out);
  }
  return out;
};

const sheet = new CSSStyleSheet();
sheet.replaceSync('.a { color: red; &:hover { color: blue; } margin: 0; }');
console.table(collectDeclarations(sheet.cssRules));
CSSNestedDeclarations unterstützt: true ┌───┬──────────────────┬────────────────┐ │ 0 │ '.a' │ 'color: red;' │ │ 1 │ '&:hover' │ 'color: blue;' │ │ 2 │ '(verschachtelt)'│ 'margin: 0px;' │ └───┴──────────────────┴────────────────┘

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Unterstützt ab Chrome/Edge 130, Firefox 132 und Safari 18.2. Ältere Browser mit CSS-Nesting-Unterstützung ziehen nachfolgende Deklarationen an den Anfang der Stilregel hoch. Dort landen sie in CSSStyleRule.style, und die Kaskade kann anders ausfallen. Prüfe die Unterstützung vorher mit typeof CSSNestedDeclarations !== 'undefined'.
  • Kein Konstruktor: new CSSNestedDeclarations() wirft einen TypeError. Neue Blöcke fügst du über insertRule() einer CSSStyleRule oder CSSGroupingRule ein, z. B. rule.insertRule('color: red;', 0).
  • Code, der von style ausgeht, liefert unvollständige Ergebnisse: Werkzeuge, die nur CSSStyleRule.style auswerten (Linter, CSS-in-JS-Tools, Editor-Erweiterungen), übersehen Deklarationen nach verschachtelten Regeln. Durchlaufe immer auch cssRules.
  • CSSNestedDeclarations hat keinen selectorText. Der Block gilt für den Selektor der übergeordneten Regel (parentRule).
  • Bei Stylesheets von fremden Ursprüngen ohne CORS-Freigabe löst der Zugriff auf cssRules einen SecurityError aus.