scope und :scope
Für Programmierer ist Scope ein geläufiger Begriff: Scope ist vereinfacht gesagt der Gültigkeitsbereich von Variablen. Auch CSS kennt einen scope – und aktuell sogar zwei Ausführungen von scope: :scope Pseudo-Klasse und @scope-Regel. In CSS ist scope der Gültigkeitsbereich von Selektoren.
:scope Pseudo-Klasse
Die Pseudoklasse :scope markiert das Wurzelelement des aktuellen Selektionskontexts (z. B. ein bestimmtes Element im DOM oder das Scoping-Root). :scope allein meint das aktuelle Wurzel-Element oder Root des Selektors oder Dokuments. :scope agiert also nicht wie die Pseudo-Klassen elem:hover oder elem:nth-child(n) als Filter für einen Selektor (main:scope geht also gar nicht), sondern ist ein Platzhalter für »aktuelles Scope-Element«.
Statt
:scope { h2 { color: tomato; } }
kann man auch gleich schreiben
body h2 { color: tomato; }
So macht :scope also keinen Sinn. Das ist meist nicht gewollt, eher ein Nebeneffekt, ein unerwünschter Nebeneffekt obendrein.
Im Stylesheet ist der »Selektionskontext« das html-Element. Also wird :scope dort immer nur html bzw. body treffen. Sinnvoll wird :scope erst in JS-Selektoren (querySelector, querySelectorAll) oder innerhalb von @scope, weil da der Kontext klar ist.
:scope ist nur in JavaScript nützlich (element.querySelectorAll(":scope > p")).
@scope
Der aktuelle Versuch, einen Gültigkeitsbereich für CSS-Stile mittels @scope festzulegen, ist nicht der Erste.
<div class="product-card"> <img src="https://www.mediaevent.de/html/img/cake-flan-300.webp" alt="Bavoir"> <h2>Bayerische Creme</h2> <p>Saftig und süß – ideal für Snacks und Kuchen.</p> <button>Kaufen</button> </div>

Bayerische Creme
Schmelzend sahniger Genuss – die Krönung nach einem Menü.

Kleiner Savarin
Reich an Kalium und perfekt zum Frühstück.
Beim Einsatz von @scope mit :scope wird jetzt die Überschrift h2 »tomato«, Text in p hat eine kleinere Schriftgröße, Bilder haben ein Seitenverhältnis 1:1. Keine dieser Eigenschaften dringt nach außen, oberhalb bleibt die Farbe der Überschriften █ .
@scope (.product-card) { :scope { display: flex; flex-direction: column; img { aspect-ratio: 1/1; object-fit: cover; } h2 { color: tomato; } p { font-size: 0.9rem; } button { margin: auto 1rem 1rem; align-self: flex-start; background: #0074d9; color: white; } :scope:hover { transform: translateY(-3px); } :scope:hover button { background: #005fa3; } } }
Unter @scope hat jetzt :scope einen stimmigen Selektionskontext, nämlich .product-card. Trotzdem bleibt das globale h2-Element unberührt. @scope verhinder, dass Stile »nach außen« sickern, nicht aber, dass globale Stile »einsickern«.
@scope weist Parallelen zum CSS-Nesting auf: Beiden schotten ihr CSS ab. Aber ein globales h2 mit einer höheren Spezifität oder späterem Laden könnte das h2 beim Nesting überschreiben.
.product-card h2 { color: green; }
Das hätte auch bei einem späteren Laden keinen Einfluß auf die Stile unterhalb von @scope.
Auch dieser neue Versuch mit @scope ist immer noch unreif. Da muss man der Weigerung von Firefox recht geben. (Firefox unterstützt @scope nicht, sondern will es erst Ende 2025 implementieren) .
@layer + Nesting
@layer + Nesting erzielen die meisten Vorteile von @scope einfacher, stabiler und ohne Fallen. @layer kapselt Styles in logische Ebenen (z. B. reset, base, components, utilities). Nesting hält Selektoren ohne BEM-Namenketten übersichtlich.