CSS light-dark()-Funktion: Natives Theme-Switching
Embed This Widget
Add the script tag and a data attribute to embed this widget.
Embed via iframe for maximum compatibility.
<iframe src="https://colorfyi.com/iframe/entity//" width="420" height="400" frameborder="0" style="border:0;border-radius:10px;max-width:100%" loading="lazy"></iframe>
Paste this URL in WordPress, Medium, or any oEmbed-compatible platform.
https://colorfyi.com/entity//
Add a dynamic SVG badge to your README or docs.
[](https://colorfyi.com/entity//)
Use the native HTML custom element.
Die Implementierung des Dunkelmodus erforderte historisch eine nicht triviale Menge an Boilerplate: eine prefers-color-scheme-Media-Query, die jede Custom Property überschreibt, JavaScript für Benutzer-Toggles, localStorage zur Persistenz von Präferenzen und ein Inline-Skript im <head>, um den Flash des falschen Themes beim Seitenaufruf zu verhindern. Die CSS-Funktion light-dark() eliminiert das alles nicht, reduziert aber die CSS-Angriffsfläche des Problems erheblich.
light-dark() ist eine CSS-Farbfunktion, die genau zwei Farbwerte annimmt und den ersten zurückgibt, wenn das aktive Farbschema hell ist, oder den zweiten, wenn es dunkel ist. Sie ist das semantische CSS-Äquivalent des ternären Operators für Farben.
Was ist light-dark()?
Die Funktionssignatur ist einfach:
color: light-dark(<light-color>, <dark-color>);
Wenn das aktive Farbschema hell ist, verwendet der Browser <light-color>. Wenn es dunkel ist, verwendet er <dark-color>. Das „aktive Farbschema" wird durch die CSS-Eigenschaft color-scheme bestimmt, die wiederum auf die System-Media-Query prefers-color-scheme oder einen explizit auf einem Element gesetzten Wert reagiert.
Die Funktion wird unterstützt in:
- Chrome/Edge: seit Version 123 (März 2024)
- Firefox: seit Version 120 (November 2023)
- Safari: seit Version 17.5 (Juni 2024)
Die globale Unterstützung liegt Anfang 2026 bei etwa 85%. Es ist eine relativ neue Ergänzung, aber die Browser-Abdeckung wächst schnell genug, um sie mit einer Fallback-Strategie in der Produktion zu verwenden.
Funktionsweise mit der color-scheme-Eigenschaft
light-dark() funktioniert nicht isoliert. Es hängt vollständig davon ab, dass die CSS-Eigenschaft color-scheme korrekt gesetzt ist. Ohne sie hat die Funktion keinen Kontext, um zu entscheiden, welchen Wert sie zurückgeben soll.
Die Eigenschaft color-scheme deklariert, welche Farbschemata ein Dokument oder Element unterstützt. Das Setzen auf :root ist der Ausgangspunkt:
:root {
color-scheme: light dark;
}
Diese einzelne Deklaration teilt dem Browser mit, dass Ihre Seite sowohl helle als auch dunkle Farbschemata unterstützt. Der Browser liest dann:
- Die
prefers-color-scheme-Systemeinstellung des Benutzers - Wendet das entsprechende Schema an
- Lässt alle
light-dark()-Aufrufe auf der Seite zum entsprechenden Wert auflösen
Damit gesetzt, wird das Definieren von theme-bewussten Farben zu einer Frage einzelner Deklarationen:
:root {
color-scheme: light dark;
--color-background: light-dark(#FFFFFF, #0F0F17);
--color-text: light-dark(#1A1A2E, #E8E8F0);
--color-border: light-dark(#DEE2E6, #2E2E4A);
--color-accent: light-dark(#2563EB, #60A5FA);
}
Keine Media Query. Keine Selektor-Überschreibungen. Eine Deklaration pro Farbe, beide Werte inline. Der Browser übernimmt das Switching automatisch basierend auf der Systempräferenz.
Auf ein einzelnes Schema beschränken
Das Setzen von color-scheme: light oder color-scheme: dark erzwingt unabhängig von der Systempräferenz ein einzelnes Schema:
/* Immer hell, unabhängig von der Betriebssystemeinstellung */
.widget {
color-scheme: light;
background: light-dark(#FFFFFF, #0F0F17);
/* Löst immer zu #FFFFFF auf */
}
/* Immer dunkel */
.dark-panel {
color-scheme: dark;
color: light-dark(#1A1A2E, #E8E8F0);
/* Löst immer zu #E8E8F0 auf */
}
Das ist nützlich für UI-Komponenten, die immer in einem bestimmten Modus erscheinen sollen – zum Beispiel ein Code-Editor, der immer einen dunklen Hintergrund haben soll, unabhängig vom umgebenden Seitenthema.
Das only-Keyword
Das Hinzufügen von only verhindert, dass die Kaskade das Schema für dieses Element überschreibt:
.forced-light {
color-scheme: only light;
}
Das ist hauptsächlich nützlich, wenn Sie ein Element in einem Dunkelmodus-Kontext haben, das hell bleiben muss.
Ersetzen von prefers-color-scheme-Media-Queries
Der traditionelle Ansatz zum Dunkelmodus mit Media Queries erfordert das Duplizieren oder Überschreiben jeder Farbvariable:
/* Traditioneller Ansatz — ausführlich */
:root {
--bg: #FFFFFF;
--text: #1A1A2E;
--accent: #2563EB;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0F0F17;
--text: #E8E8F0;
--accent: #60A5FA;
}
}
Mit light-dark() kollabiert das zu:
/* light-dark()-Ansatz — eine Deklaration pro Variable */
:root {
color-scheme: light dark;
--bg: light-dark(#FFFFFF, #0F0F17);
--text: light-dark(#1A1A2E, #E8E8F0);
--accent: light-dark(#2563EB, #60A5FA);
}
Die Variablen selbst werden selbstbeschreibend. Wenn Sie --accent: light-dark(#2563EB, #60A5FA) lesen, sehen Sie sofort beide Werte und verstehen die Beziehung. Der Media-Query-Ansatz verteilt hell und dunkel Werte über zwei separate Blöcke, was das Auditieren und Aktualisieren der Palette schwieriger macht.
Wann Media Queries noch benötigt werden
Die prefers-color-scheme-Media-Query bleibt für Nicht-Farb-Anpassungen notwendig, die sich je nach Theme ändern:
@media (prefers-color-scheme: dark) {
/* Nicht-Farb-Anpassungen, die light-dark() nicht ausdrücken kann */
img.logo {
filter: invert(1) brightness(1.2);
}
.hero-image {
opacity: 0.85;
}
}
Für alles, was eine reine Farbänderung ist, ist light-dark() sauberer. Für strukturelle oder nicht-farbige Anpassungen (Bildfilter, Deckkraft, Display-Eigenschaften) bleibt die Media Query das richtige Werkzeug.
Kombination mit CSS Custom Properties
light-dark() funktioniert innerhalb von Custom Property-Werten, wo seine volle Kraft entfaltet wird. Sie definieren alle theme-bewussten Farben bei :root, und jede Komponente der Seite referenziert diese Variablen. Wenn sich das Farbschema ändert, wird alles gleichzeitig aktualisiert.
Vollständiges Theme-System-Beispiel
:root {
color-scheme: light dark;
/* Hintergründe */
--color-bg-base: light-dark(#FFFFFF, #0F0F17);
--color-bg-elevated: light-dark(#F8F9FA, #1A1A2E);
--color-bg-overlay: light-dark(#F1F3F5, #252540);
/* Text */
--color-text-primary: light-dark(#1A1A2E, #E8E8F0);
--color-text-secondary: light-dark(#4A4A6A, #A8A8C0);
--color-text-muted: light-dark(#6C757D, #6A6A88);
--color-text-inverse: light-dark(#FFFFFF, #1A1A2E);
/* Rahmen */
--color-border: light-dark(#DEE2E6, #2E2E4A);
--color-border-strong: light-dark(#ADB5BD, #4A4A6A);
/* Interaktiv / Marke */
--color-accent: light-dark(#2563EB, #60A5FA);
--color-accent-hover: light-dark(#1D4ED8, #93C5FD);
--color-accent-subtle: light-dark(#DBEAFE, #1E3A5F);
/* Feedback */
--color-success: light-dark(#16A34A, #4ADE80);
--color-warning: light-dark(#D97706, #FCD34D);
--color-danger: light-dark(#DC2626, #F87171);
--color-success-bg: light-dark(#F0FDF4, #052E16);
--color-warning-bg: light-dark(#FFFBEB, #2D1A00);
--color-danger-bg: light-dark(#FEF2F2, #2D0A0A);
}
Komponenten referenzieren diese Variablen, ohne etwas über Theming wissen zu müssen:
.card {
background: var(--color-bg-elevated);
border: 1px solid var(--color-border);
color: var(--color-text-primary);
}
.btn-primary {
background: var(--color-accent);
color: var(--color-text-inverse);
}
.btn-primary:hover {
background: var(--color-accent-hover);
}
.alert-success {
background: var(--color-success-bg);
color: var(--color-success);
border-left: 3px solid var(--color-success);
}
Beachten Sie, dass der helle Akzent #2563EB im Dunkelmodus zu #60A5FA wechselt. Das ist beabsichtigt – das 600-Gewicht-Blau besteht WCAG AA Kontrast gegen Weiß, versagt aber gegen dunkle Hintergründe. Das 400-Gewicht macht die Farbe hell genug, um barrierefreien Kontrast auf dunklen Oberflächen zu gewährleisten. Verwenden Sie den Kontrast-Prüfer, um jede Kombination zu verifizieren, und den Schattengenerator, um den richtigen Farbton für jeden Modus zu finden.
light-dark() in andere Funktionen verschachteln
light-dark() gibt einen Farbwert zurück, daher kann es überall dort verwendet werden, wo eine Farbe gültig ist – einschließlich innerhalb anderer Funktionen:
:root {
color-scheme: light dark;
--brand: #3B82F6;
/* light-dark() innerhalb von color-mix() verwenden */
--brand-surface: color-mix(
in oklch,
var(--brand) 15%,
light-dark(white, #09090b)
);
}
Das erzeugt eine Oberflächenfarbe, die ein 15%iger Ton der Markenfarbe ist, gemischt mit Weiß im Hellmodus und Beinahe-Schwarz im Dunkelmodus – automatisch theme-bewusst.
Benutzer-Toggle hinzufügen (JavaScript)
Auf die Systempräferenz zu reagieren ist die richtige Standardvorgabe, aber Benutzer sollten sie überschreiben können. Das erfordert JavaScript, um ihre Wahl zu persistieren und den Browser-Standard zu überschreiben.
color-scheme mit JavaScript steuern
Der entscheidende Einblick ist, dass color-scheme eine CSS-Eigenschaft ist, die über JavaScript gesetzt werden kann:
// Das Farbschema programmgesteuert setzen
document.documentElement.style.colorScheme = 'dark';
document.documentElement.style.colorScheme = 'light';
// Die Überschreibung entfernen (kehrt zur Systempräferenz zurück)
document.documentElement.style.colorScheme = '';
Wenn Sie color-scheme über den Inline-Stil des Root-Elements setzen, überschreibt das die Stylesheet-Deklaration. Alle light-dark()-Werte werden neu zur entsprechenden Variante aufgelöst.
Vollständige Toggle-Implementierung
const STORAGE_KEY = 'color-scheme-preference';
function initColorScheme() {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored === 'light' || stored === 'dark') {
document.documentElement.style.colorScheme = stored;
}
// Wenn keine gespeicherte Präferenz, wird CSS color-scheme: light dark; über OS-Präferenz verwaltet
}
function toggleColorScheme() {
const current = getComputedStyle(document.documentElement)
.colorScheme
.trim();
// Nächsten Wert bestimmen
const next = current.includes('dark') ? 'light' : 'dark';
document.documentElement.style.colorScheme = next;
localStorage.setItem(STORAGE_KEY, next);
// Etwaigen Toggle-Button-Zustand aktualisieren
updateToggleButton(next);
}
function updateToggleButton(scheme) {
const btn = document.getElementById('theme-toggle');
if (!btn) return;
btn.setAttribute('aria-label',
scheme === 'dark' ? 'Zum Hellmodus wechseln' : 'Zum Dunkelmodus wechseln'
);
btn.dataset.scheme = scheme;
}
// Vor dem ersten Rendern ausführen, um Flash zu vermeiden
initColorScheme();
// Nach dem Laden des DOM an den Toggle-Button anhängen
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('theme-toggle')
?.addEventListener('click', toggleColorScheme);
});
Das Aufrufen von initColorScheme() bevor das DOM vollständig geparst ist, ist entscheidend. Wenn es zu spät läuft, sehen Benutzer mit gespeicherter Präferenz kurz das OS-Standard-Theme, bevor es wechselt – das klassische „Flash des falschen Themes". Platzieren Sie dieses Skript inline im <head> oder verwenden Sie das defer-Attribut sorgfältig (beachten Sie, dass defer-Skripte nach dem DOM-Parsen ausgeführt werden, was möglicherweise zu spät ist).
Das Anti-Flash-Muster
Der robusteste Anti-Flash-Ansatz führt ein minimales Inline-Skript im <head> aus:
<head>
<meta name="color-scheme" content="light dark">
<script>
const stored = localStorage.getItem('color-scheme-preference');
if (stored) {
document.documentElement.style.colorScheme = stored;
}
</script>
<link rel="stylesheet" href="styles.css">
</head>
Dieses Skript läuft synchron, bevor CSS angewendet wird, sodass der Browser den korrekten color-scheme-Wert beim ersten Rendern berechnet. Das <meta name="color-scheme">-Tag teilt dem Browser mit, welche Schemas erwartet werden, noch bevor CSS geparst wird – das verhindert in einigen Browsern einen kurzen weißen Flash auf Dunkelmodus-Seiten.
Migrationsleitfaden von JS-basierten Themes
Viele bestehende Dunkelmodus-Implementierungen verwenden ein data-theme-Attribut, das von JavaScript umgeschaltet wird, mit CSS-Überschreibungen in [data-theme="dark"]. Die Migration zu light-dark() ist inkrementell – Sie müssen nicht alles auf einmal ändern.
Schritt 1: color-scheme zu :root hinzufügen
:root {
color-scheme: light dark;
/* Bestehende Custom Properties bleiben unverändert */
}
Schritt 2: Variablen einzeln migrieren
Beginnen Sie mit einer einzelnen Variable als Proof of Concept. Ersetzen Sie das geteilte Deklarationsmuster durch ein einheitliches light-dark():
/* Vorher */
:root {
--bg: #FFFFFF;
}
[data-theme="dark"] {
--bg: #0F0F17;
}
/* Nachher */
:root {
color-scheme: light dark;
--bg: light-dark(#FFFFFF, #0F0F17);
}
Schritt 3: Den Toggle aktualisieren
Ändern Sie den JavaScript-Toggle vom Setzen von data-theme zum Setzen von style.colorScheme:
/* Vorher */
document.documentElement.setAttribute('data-theme', scheme);
/* Nachher */
document.documentElement.style.colorScheme = scheme;
Schritt 4: data-theme-Selektoren entfernen
Sobald alle Variablen migriert sind, entfernen Sie die [data-theme="dark"]-CSS-Blöcke.
Beide Systeme während der Migration aufrechterhalten
Sie können beide Systeme gleichzeitig betreiben. Behalten Sie [data-theme="dark"]-Überschreibungen für noch nicht migrierte Variablen. Neue Variablen verwenden light-dark(). Der JavaScript-Toggle setzt während der Übergangsphase sowohl data-theme als auch style.colorScheme.
Browser-Unterstützungs-Fallback
Für die ungefähr 15% der Browser ohne light-dark()-Unterstützung geben Sie explizite Fallbacks an:
:root {
/* Fallback: explizite Hellmodus-Werte */
--color-bg: #FFFFFF;
--color-text: #1A1A2E;
/* Progressive Enhancement mit light-dark() */
--color-bg: light-dark(#FFFFFF, #0F0F17);
--color-text: light-dark(#1A1A2E, #E8E8F0);
}
/* Fallback-Dunkelmodus für Browser ohne light-dark() */
@supports not (color: light-dark(white, black)) {
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #0F0F17;
--color-text: #E8E8F0;
}
}
}
Der @supports not (color: light-dark(white, black))-Block gilt nur für Browser, die light-dark() nicht verstehen. Moderne Browser überspringen ihn vollständig, da die negative Bedingung falsch ist.
Wesentliche Erkenntnisse
light-dark(<light-value>, <dark-value>)gibt das erste Argument in einem hellen Farbschema und das zweite in einem dunklen Schema zurück. Es ist die CSS-native Art, „diese Farbe, angepasst an das aktuelle Theme" auszudrücken.- Es hängt davon ab, dass die CSS-Eigenschaft
color-schemeauf dem Element (oder einem Vorfahren) gesetzt ist. Setzen Sie immercolor-scheme: light darkauf:root, um die automatische Anpassung überprefers-color-schemezu aktivieren. - Der Hauptvorteil gegenüber dem traditionellen Media-Query-Ansatz ist das Zusammenführen beider Theme-Werte in einer einzigen Deklaration – was die Beziehung zwischen hell und dunkel Varianten explizit und prüfbar macht.
- Benutzerüberschreibungen erfordern das Setzen von
document.documentElement.style.colorSchemevia JavaScript. Persistieren Sie die Wahl inlocalStorageund wenden Sie sie in einem Inline-<head>-Skript vor dem Laden von CSS an, um Flash zu verhindern. - Die Migration von
data-theme-attributbasierten Systemen ist inkrementell – verschieben Sie eine Variable nach der anderen vom[data-theme="dark"]-Überschreibungsmuster zumlight-dark()-Inline-Muster. - Die Browser-Unterstützung liegt 2026 bei ~85%. Geben Sie einen
@supports not-Fallback mit einem@media (prefers-color-scheme: dark)-Block für ältere Umgebungen an. - Verwenden Sie den Kontrast-Prüfer, um zu verifizieren, dass sowohl die hell- als auch die dunkelmodus-Farbwerte in jedem
light-dark()-Paar die WCAG-Kontrastanforderungen gegen ihre jeweiligen Hintergründe erfüllen, und den Schattengenerator, um den richtigen Farbton jeder Farbe für jeden Modus zu finden.