scope und :scope: Gültigkeitsbereich von Selektoren
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: Die Pseudo-Klasse :scope und die @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.