Start · Sprachen · JavaScript · Referenz · CSSScopeRule

CSSScopeRule

Schnittstelle

Stellt eine CSS-<code>@scope</code>-Regel im CSS Object Model dar und macht Scope-Wurzel (<code>start</code>), Scope-Grenze (<code>end</code>) und die enthaltenen Regeln per Skript zugänglich.

seit JavaScript Chrome/Edge 118+, Safari 17.4+, Firefox 146+ Kategorie: webapi

Signatur

interface CSSScopeRule extends CSSGroupingRule

Beschreibung

CSSScopeRule ist die CSSOM-Darstellung einer @scope-Regel. Mit @scope gelten Stilregeln nur innerhalb eines bestimmten DOM-Teilbaums: Er beginnt bei der Scope-Wurzel (z. B. .card) und endet optional an einer Scope-Grenze (z. B. .card__content). So entsteht ein „Donut-Scope“, bei dem verschachtelte Bereiche ausgenommen werden.

Die Schnittstelle erbt von CSSGroupingRule. Deshalb stehen die verschachtelten Regeln über cssRules zur Verfügung und lassen sich mit insertRule() und deleteRule() ändern. Dazu kommen zwei eigene, schreibgeschützte Eigenschaften:

  • start (string | null): der Selektor der Scope-Wurzel, oder null bei einem impliziten Scope (@scope { … } innerhalb eines <style>-Elements).
  • end (string | null): der Selektor der Scope-Grenze (der Teil nach to), oder null, wenn keine Grenze angegeben ist.

Einsatzgebiete sind vor allem Werkzeuge, die Stylesheets untersuchen oder umschreiben: DevTools-Erweiterungen, CSS-Linter im Browser, Laufzeit-Theming oder Komponentenbibliotheken, die Stile zur Laufzeit in ihren Scope einfügen. Instanzen legt man nie direkt an. Sie entstehen beim Parsen eines Stylesheets oder durch insertRule() bzw. CSSStyleSheet.replaceSync().

Parameter

Name Typ Default Beschreibung
$start string | null null Schreibgeschützte Eigenschaft: Selektor der Scope-Wurzel, z. B. .card. Bei einem impliziten Scope ist der Wert null.
$end string | null null Schreibgeschützte Eigenschaft: Selektor der Scope-Grenze (nach to). Ohne Grenze ist der Wert null.
$cssRules CSSRuleList Geerbt von CSSGroupingRule: die Liste der Regeln innerhalb des Scopes.
$insertRule(rule, index) (string, number?) => number index = 0 Geerbt: fügt eine Regel an Position index in den Scope ein und gibt diesen Index zurück.
$deleteRule(index) (number) => void Geerbt: entfernt die Regel an Position index.

Rückgabewert

Typ
CSSScopeRule
Beschreibung
Die Schnittstelle wird nicht aufgerufen. Instanzen findet man in CSSStyleSheet.cssRules oder in den cssRules anderer Gruppierungsregeln.

Beispiele

@scope-Regeln im Dokument finden und auslesen

// Alle Stylesheets nach @scope-Regeln durchsuchen
const findScopeRules = (rules, found = []) => {
  for (const rule of rules) {
    if (rule instanceof CSSScopeRule) found.push(rule);
    if (rule.cssRules) findScopeRules(rule.cssRules, found);
  }
  return found;
};

for (const sheet of document.styleSheets) {
  try {
    for (const scope of findScopeRules(sheet.cssRules)) {
      console.log(`Wurzel: ${scope.start}, Grenze: ${scope.end}, Regeln: ${scope.cssRules.length}`);
    }
  } catch {
    // Fremde Stylesheets ohne CORS lösen einen SecurityError aus
  }
}
Wurzel: .card, Grenze: .card__content, Regeln: 2

Scope-Regel mit einem konstruierbaren Stylesheet erzeugen

const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  @scope (.card) to (.card__content) {
    img { border-radius: 8px; }
    h2  { color: rebeccapurple; }
  }
`);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

const scopeRule = sheet.cssRules[0];
console.log(scopeRule instanceof CSSScopeRule); // true
console.log(scopeRule.start); // ".card"
console.log(scopeRule.end);   // ".card__content"
true .card .card__content

Regeln zur Laufzeit in einen Scope einfügen und entfernen

const sheet = new CSSStyleSheet();
sheet.replaceSync('@scope (.theme-dark) { p { color: #eee; } }');
document.adoptedStyleSheets = [sheet];

const scope = sheet.cssRules[0];
// Neue Regel ans Ende des Scopes anhängen
const idx = scope.insertRule(':scope { background: #111; }', scope.cssRules.length);
console.log(scope.cssRules[idx].cssText);

// Wieder entfernen
scope.deleteRule(idx);
console.log(scope.cssRules.length);
:scope { background: rgb(17, 17, 17); } 1

Feature-Erkennung mit Fallback

const supportsScope = typeof CSSScopeRule !== 'undefined';

if (supportsScope) {
  console.log('@scope wird unterstützt');
} else {
  // Fallback: klassische Klassen-Präfixe oder Shadow DOM verwenden
  document.documentElement.classList.add('no-css-scope');
}
@scope wird unterstützt

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Chromium ab 118, Safari ab 17.4, Firefox erst seit Version 146. In älteren Browsern wird die ganze @scope-Regel beim Parsen verworfen. Sie taucht dann auch nicht in cssRules auf. Vorher per typeof CSSScopeRule oder CSS.supports('selector(:scope)') und passendem Fallback prüfen. Achtung: :scope gibt es schon länger, daher ist dieser zweite Test nur ein grober Hinweis.
  • start und end sind schreibgeschützt. Um Wurzel oder Grenze zu ändern, entfernt man die Regel und fügt sie mit neuem Text wieder ein.
  • Bei einem impliziten Scope (@scope { … } direkt in einem <style>) ist start gleich null. Die Scope-Wurzel ist dann das Elternelement des <style>-Elements.
  • Stylesheets von fremden Ursprüngen ohne passende CORS-Header lösen beim Zugriff auf cssRules einen SecurityError aus. Deshalb den Zugriff in try…catch kapseln.
  • @scope ändert die Kaskade: Bei gleicher Spezifität gewinnt die Regel mit der geringeren DOM-Nähe zur Scope-Wurzel (Scoping Proximity). Die Wurzel selbst erhöht die Spezifität der inneren Selektoren nicht.