light-dark(): Die CSS-Funktion für farbschema-abhängige Werte
AI generated
{ }
@
CSS · Farbschema · Dark Mode
Die light-dark()-Funktion
Farbwerte direkt abhängig vom Farbschema definieren, ohne Media Query

Mit der Funktion light-dark() lässt sich ein Hell- und ein Dunkelmodus-Farbwert in einer einzigen Deklaration angeben, statt zwei getrennte prefers-color-scheme-Blöcke zu pflegen. Der Browser wählt automatisch anhand des aktuell aktiven color-scheme, welcher der beiden Werte zum Einsatz kommt, sowohl bei System-Präferenz als auch bei einem manuellen Umschalter, der die Eigenschaft überschreibt.

11 Min. Lesezeit light-dark() · color-scheme CSS Color Module Level 5

1. Das Grundprinzip: ein Wertepaar statt zwei getrennter Regelblöcke

Die Funktion light-dark(<hell>, <dunkel>) nimmt genau zwei Farbwerte entgegen: den ersten für den hellen Modus, den zweiten für den dunklen. Welcher der beiden Werte tatsächlich angewendet wird, entscheidet der Browser anhand des aktuell wirksamen color-scheme, das entweder über die CSS-Eigenschaft color-scheme auf einem Vorfahren-Element oder über die System-Präferenz prefers-color-scheme gesetzt sein kann.

Damit verschmilzt light-dark() zwei bisher getrennte Konzepte in einer Deklaration: die eigentliche Farbdefinition und die Bedingung, wann welche Farbe gilt. Das reduziert Wiederholung in Stylesheets erheblich, weil nicht mehr für jede einzelne Eigenschaft ein eigener prefers-color-scheme: dark-Block nötig ist, sondern die Fallunterscheidung direkt im Wert selbst steckt.


:root {
  color-scheme: light dark;
}

body {
  /* Ein Wertepaar statt zweier Media-Query-Bloecke */
  background: light-dark(#ffffff, #0f172a);
  color: light-dark(#1e293b, #e2e8f0);
}

2. color-scheme: die Voraussetzung, damit light-dark() überhaupt greift

Damit light-dark() funktioniert, muss auf dem Root-Element oder einem Vorfahren die Eigenschaft color-scheme: light dark; gesetzt sein. Diese Deklaration teilt dem Browser mit, dass das Dokument beide Modi unterstützt, und aktiviert erst dadurch die automatische Auswahl über light-dark(). Fehlt diese Deklaration, verhält sich light-dark() stets so, als wäre nur der helle Modus aktiv, unabhängig von der System-Präferenz des Nutzers.

Diese Kopplung ist kein Zufall: color-scheme steuert nicht nur light-dark(), sondern auch native Browser-UI-Elemente wie Formularfelder, Scrollbars und die Systemfarbe der Adressleiste auf mobilen Geräten. Wer color-scheme ohnehin für ein konsistentes natives Erscheinungsbild setzt, bekommt light-dark() quasi kostenlos als zusätzliche Fähigkeit dazu.

3. Vergleich zu prefers-color-scheme-Media-Queries

Der klassische Ansatz für Dunkelmodus-Unterstützung besteht aus einem Media-Query-Block, der alle betroffenen Eigenschaften innerhalb von @media (prefers-color-scheme: dark) { ... } neu deklariert. Das funktioniert zuverlässig, führt aber bei größeren Stylesheets dazu, dass dieselben Selektoren zweimal existieren, einmal für den Standardfall und einmal für den Dunkelmodus, was Wartung und Konsistenzprüfung erschwert, sobald ein Farbwert im einen Block geändert wird, aber im anderen vergessen wird.

Mit light-dark() steht die Fallunterscheidung direkt neben der Eigenschaft, für die sie gilt, wodurch beide Zustände beim Lesen des Codes sofort sichtbar sind und nicht über zwei entfernte Codestellen verteilt sind. Das senkt das Risiko, eine Farbe im Dunkelmodus zu vergessen, spürbar, weil es keinen zweiten Block mehr gibt, den man vergessen könnte.


/* Klassischer Ansatz: zwei getrennte Bloecke */
.card {
  background: #ffffff;
  border-color: #e2e8f0;
}

@media (prefers-color-scheme: dark) {
  .card {
    background: #1e293b;
    border-color: #334155;
  }
}

/* Mit light-dark(): ein einziger Block */
.card {
  background: light-dark(#ffffff, #1e293b);
  border-color: light-dark(#e2e8f0, #334155);
}

4. Manueller Dark-Mode-Umschalter mit color-scheme überschreiben

Ein häufiges Anforderungsmuster ist ein Umschalter in der Benutzeroberfläche, der es Nutzern erlaubt, den Dunkelmodus unabhängig von der System-Präferenz manuell zu erzwingen. Weil light-dark() sich strikt am wirksamen color-scheme-Wert orientiert, reicht es, diese Eigenschaft per JavaScript auf dem Root-Element zu setzen, etwa light oder dark statt light dark, um die automatische System-Erkennung zu übersteuern.

Der Vorteil gegenüber dem klassischen Media-Query-Ansatz ist, dass für diesen manuellen Umschalter keine zusätzliche CSS-Klasse und kein zweites Set an Selektoren nötig ist. Eine einzige JavaScript-Zeile, die color-scheme auf dem html-Element setzt, reicht aus, damit sämtliche light-dark()-Aufrufe im gesamten Stylesheet sofort den gewünschten Modus anzeigen.


<script type="text/plain">
// Nutzer waehlt manuell den Dunkelmodus, unabhaengig vom System
document.documentElement.style.colorScheme = 'dark';

// Zurueck zur System-Praeferenz
document.documentElement.style.colorScheme = 'light dark';
</script>

5. light-dark() mit Custom Properties für Design-Token-Systeme

In größeren Projekten mit einem eigenen Design-Token-System lässt sich light-dark() direkt bei der Definition der Custom Properties einsetzen, statt es an jeder einzelnen Verwendungsstelle zu wiederholen. Das zentralisiert die Farbschema-Logik an einer einzigen Stelle im Stylesheet und macht jede weitere Verwendung der Custom Property automatisch farbschema-fähig, ohne dass der aufrufende Code davon wissen muss.

Diese Zentralisierung zahlt sich besonders aus, wenn ein Token wie --surface-primary an vielen verschiedenen Stellen im Projekt verwendet wird. Ändert sich später die konkrete Dunkelmodus-Farbe, reicht eine einzige Änderung an der Token-Definition, statt Dutzende Verwendungsstellen im gesamten Projekt zu durchsuchen und einzeln anzupassen.


:root {
  color-scheme: light dark;
  --surface-primary: light-dark(#ffffff, #0f172a);
  --surface-secondary: light-dark(#f8fafc, #1e293b);
  --text-primary: light-dark(#0f172a, #f1f5f9);
  --border-subtle: light-dark(#e2e8f0, #334155);
}

.card {
  background: var(--surface-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
}

6. Browser-Support und Absicherung mit @supports

light-dark() wird von allen aktuellen Versionen von Chrome, Edge, Firefox und Safari unterstützt, nachdem die Funktion 2023 in Safari, Chrome und Firefox nahezu zeitgleich landete. Für die meisten Projekte, die keine sehr alten Browser-Versionen mehr bedienen müssen, ist die Funktion damit ohne größere Einschränkung produktionsreif einsetzbar.

Für Projekte mit strengeren Kompatibilitätsanforderungen lässt sich der Support gezielt mit @supports (color: light-dark(#fff, #000)) prüfen. Innerhalb der Regel steht die moderne Deklaration, außerhalb ein klassischer, auf Media Queries basierender Fallback, der auch in älteren Browsern korrekt funktioniert.

7. Wann sich der Umstieg von Media Queries auf light-dark() lohnt

Der Umstieg lohnt sich besonders in Projekten mit vielen einzelnen Farbdeklarationen, die bisher über zahlreiche, verstreute prefers-color-scheme-Blöcke verteilt waren. Hier reduziert light-dark() nicht nur die Zeilenzahl im Stylesheet, sondern senkt auch das Risiko, dass ein Dunkelmodus-Wert bei einer Änderung schlicht vergessen wird, weil beide Werte untrennbar in derselben Zeile stehen.

Weniger sinnvoll ist der komplette Umstieg, wenn der Dunkelmodus mehr verändert als reine Farbwerte, etwa unterschiedliche Bildquellen, Schriftgewichte oder Layout-Eigenschaften. Für solche strukturellen Unterschiede bleibt ein klassischer prefers-color-scheme-Block das richtige Werkzeug, während light-dark() gezielt für reine Farbentscheidungen eingesetzt wird, häufig sogar kombiniert im selben Projekt.

8. Praxisbeispiel: ein vollständiges Farbschema für eine Komponente

Am Beispiel einer Karten-Komponente mit Rahmen, Schatten und einem Akzentfarbton zeigt sich das Muster in voller Breite: jede visuelle Eigenschaft, die sich zwischen hell und dunkel unterscheidet, bekommt ihr eigenes light-dark()-Wertepaar, während strukturelle Eigenschaften wie Padding oder Border-Radius unverändert bleiben, weil sie ohnehin unabhängig vom Farbschema sind.

Wichtig ist, auch Schattenfarben nicht zu vergessen: Ein Schatten, der im hellen Modus dezent grau wirkt, kann im dunklen Modus komplett unsichtbar werden, wenn er nicht ebenfalls über light-dark() angepasst wird. Ein dunklerer, aber intensiverer Schattenwert im Dunkelmodus sorgt dafür, dass die Tiefenwirkung der Komponente in beiden Modi erhalten bleibt.


.product-card {
  background: light-dark(#ffffff, #1e293b);
  border: 1px solid light-dark(#e2e8f0, #334155);
  box-shadow: 0 4px 12px light-dark(rgba(15,23,42,0.08), rgba(0,0,0,0.4));
  color: light-dark(#0f172a, #f1f5f9);
  padding: 1.5rem;
  border-radius: 0.75rem;
}

.product-card .price {
  color: light-dark(#7c3aed, #c4b5fd);
}

9. Barrierefreiheit: Kontrastprüfung für beide Modi getrennt durchführen

Weil light-dark() beide Farbpaare so kompakt nebeneinander stellt, entsteht leicht der Eindruck, ein Wertepaar sei automatisch für beide Modi kontrastsicher, nur weil es syntaktisch zusammengehört. Tatsächlich müssen Kontrastverhältnisse für hellen und dunklen Modus unabhängig voneinander geprüft werden, denn ein Grauton, der im hellen Modus einen ausreichenden Kontrast zu Weiß bietet, kann im Dunkelmodus gegen einen dunklen Hintergrund deutlich zu schwach wirken.

Praktisch bedeutet das, jedes light-dark()-Paar mit einem Kontrast-Checker zweimal zu prüfen, einmal für die Kombination aus hellem Vordergrund- und Hintergrundwert, einmal für die dunkle Variante. Werkzeuge, die WCAG-Kontrastverhältnisse berechnen, sollten deshalb in den Review-Prozess für neue light-dark()-Deklarationen aufgenommen werden, nicht erst nachträglich beim fertigen Screenshot.

Ansatz Codezeilen pro Farbe Risiko vergessener Dunkelmodus-Werte Geeignet für
@media (prefers-color-scheme: dark) 2 (zwei Blöcke) Höher, Werte örtlich getrennt Strukturelle Unterschiede, nicht nur Farbe
light-dark() pro Eigenschaft 1 Niedriger, Werte in einer Zeile Einzelne, verstreute Farbdeklarationen
light-dark() in Custom Properties 1 (zentral) Am niedrigsten, ein Token pro Farbe Design-Token-Systeme
Manueller JS-Umschalter über color-scheme 0 zusätzlich Unverändert zur gewählten Methode Nutzergesteuerter Dark-Mode-Toggle

Mironsoft

Modernes CSS, Layout-Architektur und Rendering-Performance

CSS, das wartbar bleibt statt mit jeder Änderung zu brechen?

Wir prüfen bestehende Stylesheets auf Spezifitäts-Chaos und Layout-Thrashing und bauen daraus eine CSS-Architektur mit Cascade Layers, Custom Properties und modernen Layout-Primitiven, die auch nach dem zehnten Feature noch verständlich ist.

CSS-Audit

Spezifität, Cascade-Konflikte und ungenutzte Selektoren systematisch aufdecken.

Architektur-Refactoring

Cascade Layers, Custom Properties und Design Tokens sauber einführen.

Performance-Tuning

Layout-Thrashing, teure Selektoren und Rendering-Engpässe gezielt beheben.

10. Zusammenfassung

light-dark() in CSS: Das Wichtigste auf einen Blick

Grundprinzip

light-dark(hell, dunkel) definiert ein Farbwertepaar in einer Deklaration, der Browser wählt anhand von color-scheme aus.

Voraussetzung

Ohne color-scheme: light dark; auf dem Root-Element bleibt light-dark() dauerhaft beim hellen Wert.

Vorteil ggü. Media Query

Beide Zustände stehen nebeneinander im Code, was das Vergessen eines Dunkelmodus-Werts unwahrscheinlicher macht.

Grenzen

Für strukturelle Unterschiede zwischen den Modi, nicht nur Farbe, bleibt ein klassischer prefers-color-scheme-Block nötig.

11. FAQ: light-dark() in CSS: Das Wichtigste auf einen Blick

1Was macht die light-dark() Funktion in CSS?
light-dark() nimmt zwei Farbwerte entgegen, einen für den hellen und einen für den dunklen Modus, und der Browser wählt automatisch den passenden anhand des aktuellen color-scheme aus.
2Was ist die Voraussetzung, damit light-dark() funktioniert?
Auf dem Root-Element oder einem Vorfahren muss color-scheme: light dark; gesetzt sein. Ohne diese Deklaration bleibt light-dark() immer beim hellen Wert.
3Wie unterscheidet sich light-dark() von prefers-color-scheme-Media-Queries?
light-dark() definiert beide Farbwerte in einer einzigen Zeile, während ein Media Query zwei getrennte Regelblöcke erfordert. Das senkt das Risiko, einen Dunkelmodus-Wert zu vergessen.
4Kann ich den Dunkelmodus manuell erzwingen, unabhängig vom System?
Ja, indem ein JavaScript-Umschalter die color-scheme-Eigenschaft auf dem Root-Element direkt auf light oder dark setzt, statt light dark, was die System-Präferenz übersteuert.
5Welche Browser unterstützen light-dark()?
Alle aktuellen Versionen von Chrome, Edge, Firefox und Safari, nachdem die Funktion 2023 nahezu zeitgleich in allen großen Browsern landete.
6Sollte ich light-dark() für Custom Properties oder direkt in Selektoren verwenden?
Für Design-Token-Systeme empfiehlt sich die zentrale Definition in Custom Properties, damit eine spätere Farbänderung nur an einer Stelle gepflegt werden muss.
7Ersetzt light-dark() prefers-color-scheme-Media-Queries komplett?
Nicht immer. Für strukturelle Unterschiede zwischen den Modi, etwa andere Bilder oder Layouts, bleibt ein klassischer Media-Query-Block das richtige Werkzeug.
8Muss ich Kontrastverhältnisse für beide Modi separat prüfen?
Ja. Ein Farbwert, der im hellen Modus ausreichend Kontrast bietet, kann im dunklen Modus zu schwach sein. Beide Kombinationen sollten unabhängig geprüft werden.
9Beeinflusst color-scheme auch andere Dinge als light-dark()?
Ja, color-scheme steuert zusätzlich native Browser-UI wie Formularfelder, Scrollbars und die Systemfarbe der Adressleiste auf mobilen Geräten.
10Wie sichere ich light-dark() für ältere Browser ab?
Mit @supports (color: light-dark(#fff, #000)) lässt sich gezielt prüfen, ob der Browser die Funktion unterstützt, und ein klassischer Media-Query-Fallback außerhalb der Regel greift für ältere Browser.