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 und @scope

: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>
Bavoir

Bayerische Creme

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

Savarin

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.

Suchen auf mediaevent.de