Sicheres Verwenden von Modernem CSS: Anker, Grid-Lanes, Scope und light-dark()
Erfahren Sie, wie Ankerpositionierung, Popover-Funktionen, Gitterstrukturen, Ansichtsübergänge, light-dark() sowie @scope JavaScript-Bibliotheken ersetzen können und wie man jede dieser Methoden mit Ersatzlösungen einsetzt.
Quellen: CSS Can Already Do This. Developers Are Still Scared to Ship It.
Viele Frontend-Bundles enthalten weiterhin Bibliotheken, deren einzige Aufgabe darin besteht, herauszufinden, wo sich ein Tooltip platzieren soll – wie zum Beispiel Floating UI oder sein Vorgänger Popper – sowie weitere Bibliotheken, die Karten in ein Pinterest-ähnliches Raster anordnen. Browser können nun beides nativ erledigen, zusammen mit mehreren anderen Aufgaben, die früher JavaScript benötigten. Dennoch haben nur wenige Teams diese Abhängigkeiten beseitigt. Dieser Leitfaden behandelt fünf CSS-Funktionen, die gängigen Bibliothekskodeteile ersetzen können, erklärt, wie jede davon funktioniert, und zeigt, wie man sie ohne Risiko auf ungleichmäßige Browserunterstützung einsetzen kann.
Gleichzeitig gewünscht und vermieden
Entwicklerumfragen zeigen diese Spannung gut wider. In den für 2026 veröffentlichten Ergebnissen des State of CSS wurde die Ankerpositionierung als die neue Funktion gewählt, auf die Entwickler am meisten gespannt waren – und sie übertrifft dabei :has(), das mittlerweile so weit verbreitet ist, dass es nicht mehr als neu wahrgenommen wird. Derselbe Umfrage zufolge wurden außerdem Funktionen genannt, die Menschen absichtlich vermieden, weil sie dem Browser-Support noch nicht vertrauten – und auch hier stand die Ankerpositionierung an erster Stelle. Um diese Lücke zu schließen, geht es hauptsächlich darum, Funktionen über Feature-Queries zu nutzen. Die Umfrageergebnisse sowie der Support-Status ändern sich schnell, daher sollten sie als Momentaufnahme betrachtet werden; vor der Nutzung einer Funktion sollten stets aktuelle Kompatibilitätsdaten geprüft werden.
Ankerpositionierung anstelle einer Tooltip-Bibliothek
Der JavaScript-Ansatz fügt ein schwebendes Element zu seinem Auslöser hinzu, indem er beide misst und die Position bei jedem Scrollen sowie bei einer Änderung der Größe neu berechnet. Die Ankerpositionierung verlagert diese Beziehung in das CSS.
Dort gibt der Auslöser einen Namen an, und das Menü positioniert sich entsprechend diesem Namen. Die letzte Deklaration ersetzt die Kollisionserkennung einer Bibliothek:
.trigger {
anchor-name: --menu-trigger;
}
.menu {
position: fixed;
position-anchor: --menu-trigger;
top: anchor(bottom);
left: anchor(center);
position-try-fallbacks: flip-block, flip-inline;
}
Jeder Bestandteil hat eine spezifische Funktion:
anchor-namegibt einem Element einen gestrichelten Identifikator, anhand dessen andere Elemente positioniert werden können.position-anchorweist ein positioniertes Element an, welchen benannten Anker es folgen soll.anchor()liest eine Koordinate, wie den unteren Rand oder die horizontale Mitte des Ankers, direkt von diesem Element ab.
position-try-fallbacks listet die Alternativen auf, die der Browser ausprobiert, wenn das Element den Ansichtsbereich überschreiten würde; flip-block und flip-inline spiegeln es vertikal oder horizontal wider.Kombination mit dem popover-Attribut
Das popover-Attribut, das ebenfalls mitgeliefert wird und aber weitgehend ignoriert wird, regelt das Verhalten eines Dropdowns: Ein Button mit popovertarget schaltet das Element mit der entsprechenden id ein, ohne dass ein Skript erforderlich ist:
<button popovertarget="menu">Options</button>
<div id="menu" popover anchor-name-target="--menu-trigger">...</div>
Achten Sie bei diesem Codeausschnitt darauf: anchor-name-target ist kein standardmäßiges HTML-Attribut, daher sollten Sie es nicht unverändert kopieren. Verbinden Sie den Popover in CSS mit seinem Anker mithilfe von anchor-name und position-anchor, wie oben gezeigt. Einige Browser betrachten außerdem die auslösende Schaltfläche als impliziten Anker für einen durch popovertarget geöffneten Popover; prüfen Sie die aktuelle Dokumentation, bevor Sie sich darauf verlassen.
Was popover nativ bietet, ist eine Darstellung in der obersten Schicht, sodass das Menü über allem angezeigt wird, ohne dass es zu Konflikten bezüglich des z-Index innerhalb der Anwendung kommt. Zudem wird das Menü einfach geschlossen, wenn der Benutzer außerhalb klickt oder die Escape-Taste drückt, und es wird ein sinnvolles Fokushandling beim Öffnen und Schließen gewährleistet. Es behält den Fokus nicht auf dieselbe Weise wie ein modales dialog, daher sollten Sie für wirklich modales Inhalte stattdessen dialog verwenden.
Um einen umfassenderen Überblick über Browser-APIs zu erhalten, die npm-Pakete überflüssig machen, sehen Sie unsere Übersicht über native Browser-APIs, die beliebte Pakete ersetzen.
Natives Masonry mit Grid-Lanes
Since CSS Grid 2017 in den Browsern verfügbar wurde, erforderten Masonry-Anordnungen weiterhin JavaScript – weshalb die Masonry-Bibliothek sowie ähnliche Pakete Millionen von Mal installiert wurden. Das ändert sich nun. Die folgende Regel beschreibt die vollständige Anordnung:
.gallery {
display: grid-lanes;
gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
Jede Karte wird in die Spalte gelegt, die derzeit am meisten Platz bietet, sodass die Elemente dicht beieinander liegen und keine ungleichmäßigen Lücken entstehen. Es gibt keinen ResizeObserver, und es wird auch nicht jedes Mal, wenn ein Bild geladen ist, eine Neuberechnung der Spalten vorgenommen. Die Syntax war Gegenstand jahrelanger Debatten zwischen Browserherstellern, wobei Apple und Google unterschiedliche Ansätze bevorzugten, bis display: grid-lanes als Kompromiss hervorkam.
Laut den Unterstützungsdaten zum Zeitpunkt der Erstellung führte Safari diese Funktion zuerst ein, während Chrome und Firefox sie zunächst hinter Flags zurückhielten. Das erklärt, warum nur so wenige Websites sie nutzen und warum es jetzt sinnvoll ist, sie zu implementieren. Legen Sie grid-lanes in einen @supports (display: grid-lanes)-Block und verwenden Sie ein herkömmliches Grid als Ersatz.
Bildschirmübergänge – mit großer Vorsicht
Hier ist Vorsicht angebracht. Es gibt zwar Unterstützung für die View Transition API, diese ist jedoch ungleichmäßig verteilt, wodurch sie zusammen mit der Positionierung von Ankerpunkten zu den am meisten gemiedenen Funktionen zählt – und diese Zurückhaltung ist berechtigt.
Der grundlegende Mechanismus ist einfach: Eine DOM-Änderung wird in document.startViewTransition() eingebettet, wodurch der Browser die alten und neuen Zustände aufnimmt und zwischen ihnen schrittweise wechselt, ohne dass eine Animationsbibliothek oder manuelle Aufzeichnungen vorher und nachher erforderlich sind. Die unten stehenden Pseudo-Elemente steuern diese Standardüberblendung und verkürzen sie hier auf 0,3 Sekunden:
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.3s;
}
Heute ist es als progressive Enhancement vertrauenswürdig. Ein Browser, der die API nicht besitzt, wechselt einfach in den neuen Zustand, sodass nichts kaputtgeht. Das macht es für nicht-kritische Situationen wie das Wechseln von Seiten oder das Umordnen einer Liste sicher. In Skripten sollte man überprüfen, ob document.startViewTransition vorhanden ist, bevor man es aufruft, und andernfalls direkt die Aktualisierung vornehmen.
Eine Palette für Hell und Dunkel mit light-dark()
Ein typischer Dunkelmodus verwendet zwei vollständige Farbsysteme – eines innerhalb einer prefers-color-scheme: dark-Media-Abfrage und eines außerhalb. Die light-dark()-Funktion fasst jedes Paar zu einer einzigen Deklaration zusammen.
Der folgende Codeausschnitt wählt zunächst mit color-scheme das Dokument für beide Schemata aus, was von light-dark() zur Funktionsfähigkeit benötigt wird, und gibt anschließend für jede Eigenschaft ihre hellen und dunklen Werte nebeneinander an:
:root {
color-scheme: light dark;
}
body {
background: light-dark(#ffffff, #1a1a1a);
color: light-dark(#111111, #eeeeee);
}
Sobald das color-scheme festgelegt ist, führt jeder Aufruf von light-dark() zum richtigen Wert entsprechend den Systemeinstellungen des Benutzers, und es ist nicht mehr notwendig, Medienabfragen im Stylesheet zu duplizieren. Weitere Möglichkeiten zur Implementierung von Themen finden Sie in unserer Vergleichsstudie zu Dark-Mode-Techniken.
Stile mit @scope einschränken
Ein großer Anreiz für CSS-in-JS oder strenge BEM-Namenskonventionen ist das sogenannte Specificity-Leakage: Eine Regel für .card, die ursprünglich für ein bestimmtes Komponenten bestimmt war, gestaltet auch einen unverwandten .card, der tiefer in der Markup-Struktur eines anderen Elements liegt. @scope beschränkt Stile nativ auf einen Unterbaum.
In der folgenden Regel gelten die Absatzstile innerhalb von .card, enden aber bei jedem Element vom Typ .card-nested:
@scope (.card) to (.card-nested) {
p {
color: var(--card-text);
}
}
Der erste Selektor legt die Wurzel des Scope fest. Die to-Klausel legt eine untere Grenze fest, wodurch ein Bereich entsteht, in dem eine verschachtelte Komponente ihre eigenen Styles verwalten kann, anstatt die des Elternteils zu erben. Dafür sind weder ein Build-Schritt, generierte Klassennamen noch laufzeitbasiertes JavaScript erforderlich. Es ersetzt zwar nicht alles, was CSS-in-JS leistet – wie beispielsweise Styles, die aus Komponenteneigenschaften berechnet werden –, doch es beseitigt einen der Hauptgründe, warum Teams dieses Konzept überhaupt anwenden.
Der Browser ist das Ökosystem
Sämtliche fünf Funktionen sind heute in mindestens einem echten Browser verfügbar, und keines davon hängt von React, einem Bundler-Plugin oder einer Framework-Version ab. Der Unterschied zwischen dem, was CSS leisten kann, und dem, was Teams tatsächlich einsetzen, beruht größtenteils auf Gewohnheit: Seit einem Jahrzehnt bedeutet die Lösung eines UI-Problems den Installieren einer Paket.
Wählen Sie einen Ort in Ihrem Projekt, an dem eine JavaScript-Lösung für eines dieser Probleme verwendet wird, ersetzen Sie diese Lösung durch einen Code hinter @supports und schauen Sie, was kaputtgeht. In der Regel weniger, als man erwarten würde.
Häufige Fragen
Ist die Ankerpositionierung bereits für die Produktion bereit?
Sie ist bereits verfügbar und kann heute hinter einer @supports-Prüfung eingesetzt werden. Ihre Platzierung auf der Liste der am meisten vermiedenen Funktionen spiegelt Vorsicht bezüglich einer ungleichen Implementierung in verschiedenen Browsern wider, nicht ein defektes Feature. Die Kombination mit einer Ersatzlösung, wie beispielsweise einer einfacheren statischen Anordnung, stellt das angemessene Maß an Sorgfalt dar.
Braucht man immer noch eine Mauerwerksbibliothek?
Für ein neues Projekt wahrscheinlich nicht, vorausgesetzt display: grid-lanes befindet sich innerhalb eines @supports-Blocks mit einem normalen Grid als Ersatz. Bei einer bestehenden Produktionslayout mit strengen Browser-Unterstützungsanforderungen sollte die Bibliothek noch eine Weile beibehalten werden.
Welche Funktion sollten Sie zuerst übernehmen?
light-dark(). Es handelt sich um eine einzeilige Änderung pro Farbwert, zum Zeitpunkt der Erstellung hatte es die breiteste Unterstützung von allen fünf Optionen und beseitigt einen Block mit dupliziertem CSS für den Dunkelmodus ohne Layout-Risiken.
Kernpunkte
- Betrachten Sie jede Funktion als progressive Enhancement: natives Verhalten, wo es unterstützt wird, sowie eine bestehende Lösung an anderer Stelle.
- Die Positionierung eines Ankers in Kombination mit
popoverdeckt die meisten Anforderungen an Tooltips und Dropdowns ab, binden Sie den Anker jedoch in CSS ein und verwenden Siedialog, wenn Sie ein echtes Modalfenster benötigen. grid-lanessowie Ansichtsübergänge sind am wenigsten ausgereift; schützen Sie sie mit@supportsoder einer Laufzeitprüfung ab.light-dark()und@scopelöschen Code sofort und bergen das geringste Risiko.