EMZETT.
Login

Dark Mode und Theming mit CSS-Variablen umsetzen

Kurz: Mit CSS-Variablen für Farben, der Media Query prefers-color-scheme und einem Umschalter lässt sich ein Dark Mode sauber bauen, der die Systemeinstellung respektiert und die Wahl speichert.

Genauer: Ein guter Dark Mode ist mehr als Farben invertieren: ausreichend Kontrast, gedämpfte Flächen, angepasste Schatten und Bilder. Mit Design-Tokens (benannte Farbvariablen) bleibt alles wartbar.

Im Detail

Variablen als Design-Tokens

:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --muted: #5c6370;
  --accent: #0b6bcb;
  --border: #d9dde3;
  color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #12141a; --text: #e8eaf0; --muted: #9aa3b2;
    --accent: #6ea8ff; --border: #2a2f3a;
  }
}
:root[data-theme="dark"] { --bg: #12141a; --text: #e8eaf0; /* … */ }
body { background: var(--bg); color: var(--text); }

Nutze semantische Namen (--bg, --text, --accent), nicht --blau. color-scheme: light dark färbt Formularelemente, Scrollbars passend. Neu: light-dark()-Funktion und @property.

System, Umschalter, Speichern

  • System folgen per prefers-color-scheme (Standard).
  • Umschalter Hell / Dunkel / System: setzt data-theme am <html>; Auswahl in localStorage merken (in try/catch).
  • Flackern vermeiden (FOUC): kleines Inline-Skript im <head>, das die Einstellung vor dem ersten Rendern setzt.
  • In Next.js: Bibliothek wie next-themes oder eigener Provider; auf Hydration-Unterschiede achten (suppressHydrationWarning am html).
  • Dazu <meta name="theme-color"> für die Browserleiste.

Gestaltung im Dunkeln

  • Kontrast nach WCAG prüfen (Text ≥ 4,5:1), nicht reines Schwarz/Weiß (#000/#fff blendet): eher #12141a und #e8eaf0.
  • Akzentfarben aufhellen und Sättigung senken.
  • Erhöhung durch hellere Flächen statt Schatten.
  • Bilder/Logos: dunkle Varianten, filter/mix-blend-mode, SVG mit currentColor.
  • Diagramme und Code-Highlighting mit eigenen Paletten.
  • Transparente PNGs auf Dunkel testen.
  • Retro-/Gaming-Stile sind eigene Themes: dieselbe Variablenstruktur, andere Werte.

Testen und Barrierefreiheit

In DevTools Rendering → prefers-color-scheme emulieren; auf echten Geräten (OLED, Sonne) testen. Fokusrahmen und Fehlerfarben in beiden Modi sichtbar. Auch forced-colors/Hochkontrast (@media (forced-colors: active)) und prefers-contrast respektieren. Druckstil hell halten. Farbe nie allein als Information (Muster/Text ergänzen). Dokumentiere Tokens in einem kleinen Styleguide.

Siehe auch: CSS-Grundlagen, Moderne CSS-Funktionen, Barrierefreie Webseiten