Wie man einen großartigen Dark-Mode-Schalter erstellt
Übersetzung von How to Create a Great Dark Mode Switch von James R Meyer.
Was sind die größten Schwierigkeiten beim Einrichten eines Hell-/Dunkel-Modus-Umschalters auf Ihrer Website? Bis vor Kurzem drehten sich die Schwierigkeiten alle darum, dass man, um sowohl den Hell- als auch den Dunkelmodus für eine Website zu implementieren, zwei separate Speicherorte für jede Klasse oder ID benötigt, in denen man die Deklarationen für diese Klasse oder ID schreibt; einen für die Hauptdefinition dieser ID oder Klasse und einen weiteren für die abweichende Definition, die sich auf den Dunkelmodus bezieht (der Einfachheit halber wird hier davon ausgegangen, dass der Hellmodus der Standard ist, aber die Methode ist dieselbe, wenn der Dunkelmodus der Standard ist). Wäre es nicht so viel einfacher, wenn die Definitionen für Hell- und Dunkelmodus innerhalb einer einzigen Gesamtdeklaration stünden?
Hier kommt eine relativ neue Ergänzung zu CSS ins Spiel - es gibt jetzt die Eigenschaft `color-scheme` und die Eigenschaft `light-dark`. Diese beiden Eigenschaften ermöglichen es Ihnen, zwei verschiedene Werte für eine Farbe in derselben Zeile anzugeben, einen für den Hellmodus und einen für den Dunkelmodus. Das vereinfacht das Hinzufügen, Bearbeiten und Pflegen von Farben für den Hell- und den Dunkelmodus erheblich. Das ist die Grundlage für die hier beschriebene Methode zur Implementierung eines Dunkel-/Hell-Umschalters für eine Website.1
Sie sollten sich bewusst sein, dass das eine recht neue Ergänzung der CSS-Regeln ist und es daher immer noch einige Browser gibt, die diese Eigenschaften nicht unterstützen werden. Sie können die aktuelle Browser-Unterstützung unter light-dark browser support einsehen und entscheiden, ob das eine praktikable Option für Ihre Website ist.
Obwohl diese Methode ein großer Fortschritt ist, gibt es einen kleinen Haken: Sie gilt nur für Farben. Wenn man also möchte, dass sich eine andere Eigenschaft, die nichts mit Farben zu tun hat, beim Wechsel zwischen Hell- und Dunkelmodus ändert, muss man dafür eine andere Methode verwenden. Es gibt zwar eine CSS-if( )-Bedingung, mit der sich Änderungen nicht-farbiger Eigenschaften je nach Hell- oder Dunkelschema sehr einfach umsetzen lassen (ich habe eine Demo, siehe die Demo-Links unten), aber diese wird derzeit nur von sehr wenigen Browsern unterstützt. Es ist daher besser, sie vorerst zu vermeiden, bis die Browserunterstützung besser ist.2 Derzeit müssen wir also weiterhin separate prefers-color-scheme-Deklarationen verwenden. Wenn man beispielsweise die Farben eines Bildes invertieren möchte, muss man in einem Modus den CSS-Befehl filter: invert(1) anwenden und im anderen nicht – und das muss aktuell innerhalb einer prefers-color-scheme-Deklaration erfolgen.3 Da der Großteil der Änderungen zwischen den Modi farbbezogen ist, bleibt die Anzahl solcher prefers-color-scheme-Deklarationen jedoch gering und leicht handhabbar. Dennoch müssen wir uns damit auseinandersetzen, wenn wir einen Hell-/Dunkelmodus-Schalter implementieren möchten. Wie das funktioniert, beschreibe ich später – zunächst ein paar Informationen darüber, wie Hell- und Dunkelmodus arbeiten.
Die Grundlagen von Hell- und Dunkelmodus
In diesem Abschnitt wird die grundlegende Funktionsweise von Hell- und Dunkelmodus erklärt (wenn du mit dem Thema bereits vertraut bist, kannst du diesen Abschnitt überspringen). Zunächst ist zu beachten, dass dem Nutzer zwei mögliche Dunkelmodi zur Verfügung stehen:
- wenn der Nutzer den gesamten Browser bzw. das System auf Dunkelmodus eingestellt hat, und
- wenn der Nutzer für eine bestimmte Website durch Klicken auf eine Schaltfläche auf der Seite den Hell- oder Dunkelmodus gewählt hat
Beachte, dass der Dunkelmodus des Browsers durch das Betriebssystem ausgelöst werden kann, wenn dieses im Dunkelmodus ist, oder der Browser kann unabhängig vom System seinen Modus auf Hell oder Dunkel setzen. Im Folgenden wird der Browser-/Systemmodus einfach als „System“ bezeichnet (da wir versuchen, die Absichten des Nutzers zu respektieren, sei angemerkt, dass der Nutzer die Einstellung seines Betriebssystems im Browser überschreiben kann, aber die Webseite wird dies als „System“ wahrnehmen).
Die neuen Eigenschaften color-scheme und light-dark funktionieren folgendermaßen: light-dark ist eine Funktion, die eine Farbe zurückgibt, z. B.:
.someClassName {
background: light-dark(white, hsl(52, 36%, 9%));
}
wobei die erste Farbe angezeigt wird, wenn der helle Modus aktiv ist - die zweite, wenn der dunkle Modus aktiv ist. Sie können Variablen verwenden, um Farben zu speichern, die an mehreren Stellen verwendet werden, zum Beispiel:
:root
--primary-color: light-dark(#14172b, #f6f4ec);
--secondary-color: light-dark(#f6f4ec, #14172b);
--text-color: light-dark(#2e2590, #e1e6db);
--bg-color: light-dark(#dbe9c2, #7a1522);
}
sodass Sie sich nur auf die Variable beziehen müssen, z. B.:
.someClassName{
color: var(--primary-color);
}
Beachte, dass innerhalb der light-dark()-Funktion nur tatsächliche Farbangaben verwendet werden können; Begriffe wie inherit, initial, revert oder unset sind nicht zulässig. Um die Farb-Funktion light-dark() zu aktivieren, muss color-scheme auf einen der Werte light, dark oder light dark gesetzt sein. Dies kann zum Beispiel geschehen, indem Eigenschaften deklariert werden, die auf die Webseite angewendet werden können, z. B.:
:root {
color-scheme: dark;
}
Mit dieser Methode besteht das Erstellen eines Schalters, mit dem der Nutzer die Seite in den gewünschten Hell- oder Dunkelmodus versetzen kann, ohne die Systemeinstellung zu ändern, einfach darin, das auf die Seite angewendete color-scheme zu ändern.
Die andere, traditionelle Methode für Hell-/Dunkelmodus besteht darin, dass der Hauptteil des CSS-Codes die Werte für den Standardmodus (in der Regel Hell) definiert und dann ein separater Abschnitt mit einer Media Query die Werte für den Nicht-Standardmodus enthält, z. B.:
@media (prefers-color-scheme: dark) {
/* Code for Dark mode */
.someClassName {color : red}
}
Wenn der Nutzer den Systemmodus auf „dunkel“ eingestellt hat, wird die Seite gemäß dem Code im @media-Abschnitt dargestellt. Dabei wird vorausgesetzt, dass dein Code den Hellmodus als Standardmodus der Webseite verwendet; wenn du stattdessen den Dunkelmodus als Standard nutzen möchtest, platzierst du einfach alle Eigenschaftsänderungen für den Hellmodus innerhalb eines @media (prefers‑color‑scheme: light)-Abschnitts.
Mit dieser Methode ist das Erstellen eines Schalters, mit dem der Nutzer zwischen Hell- und Dunkelmodus wechseln kann, ohne die Systemeinstellung zu ändern, etwas aufwändiger. Der herkömmliche Ansatz besteht darin, eine Klasse oder einen Stil auf die Webseite anzuwenden, die denselben Code enthält wie der @media (prefers‑color‑scheme: dark)-Abschnitt. Die hier verwendete Methode ist jedoch etwas anders. Ich werde sie anhand eines Beispiels erklären:
@media (prefers-color-scheme: dark) {
.someClassName {border-top : 2px solid red;}
}
Wenn der Haupt-CSS-Code für die Klasse someClassName keinen Rahmen im Hellmodus definiert, erscheint bei gesetzter Systemeinstellung auf Hellmodus kein Rahmen – wird jedoch der Dunkelmodus bevorzugt, erscheint ein Rahmen. Der Trick besteht darin, mit JavaScript diese Media-Query-Regel zu finden, und dann den Wert der Media Query von prefers-color-scheme: dark auf prefers-color-scheme: light zu ändern, sodass der Browser nun Folgendes sieht:4
@media (prefers-color-scheme: light) {
.someClassName {border-top : 2px solid red;}
}
Das bedeutet: Wenn die System-Einstellung auf Hellmodus gesetzt ist und der Nutzer auf den Schalter für den Dunkelmodus klickt, wird der Browser dazu gebracht, die Regeln innerhalb der Media Query anzuwenden. Ebenso, wenn die System-Einstellung auf Dunkelmodus steht, der Nutzer jedoch den Hellmodus erzwingen möchte, ändern wir die Media Query entsprechend von prefers-color-scheme: dark zu prefers-color-scheme: light. Wenn JavaScript deaktiviert oder aus irgendeinem Grund nicht funktionsfähig ist, wird standardmäßig die System-Einstellung verwendet. Du kannst beliebig viele prefers-color-scheme: dark- und prefers-color-scheme: light-Abschnitte in deinen CSS-Dateien und in <style>-Tags innerhalb deines HTML-Dokuments verwenden.5 Du schreibst und pflegst deinen CSS-Code einfach so, als würdest du deine Webseite auf die System-Hell-/Dunkelmodus-Einstellung ausrichten – um alles andere brauchst du dich nicht zu kümmern.
Um meinen Hell-/Dunkelmodus-Schalter zu implementieren, musst du nicht im Detail wissen, wie das JavaScript funktioniert – du kannst einfach den entsprechenden Code im oberen Bereich des <head> deiner Webseiten einfügen. Dieser Head-Code sollte vor allen Ressourcen wie CSS-Dateien geladen werden, um ein Flackern beim Laden der Seite zu vermeiden. Du musst außerdem einen Link zur JavaScript-Datei hinzufügen; um das Laden der Seite nicht zu blockieren, füge ihn entweder am Ende deines HTML-Dokuments ein oder im <head> mit dem Attribut defer.
Details zum Code
Der notwendige Code zur Bereitstellung dieser Funktionalität ist recht klein und wird unten beschrieben. Eine Demo der wichtigsten Dateien findest du auf der einfachen Dunkelmodus-Demo-Seite.
Hier kannst du Kopien der grundlegenden Demodateien herunterladen:
- HTML-Code herunterladen: dark-mode-demo.html
- Basis-CSS herunterladen: dark-mode-demo.css
- JavaScript-Code herunterladen: dark-mode-demo.js
Es gibt auch Demodateien mit einer Nachricht, die dem Nutzer erklärt, wie man zur System-Einstellung (Hell oder Dunkel) zurückkehrt – siehe einfache Dunkelmodus-Demo-Seite mit Nachricht. Du kannst diese Demodateien hier herunterladen:
- HTML-Code herunterladen: dark-mode-demo-with-msg.html
- Basis-CSS herunterladen: dark-mode-demo-with-msg.css
- JavaScript-Code herunterladen: dark-mode-demo-with-msg.js
Und für eine Demo zur Verwendung der CSS-if( )-Bedingung siehe einfache Dunkelmodus-Demo-Seite mit CSS-if()-Bedingung – du kannst die entsprechenden Demodateien hier herunterladen:
- HTML-Code herunterladen: dark-mode-demo-CSS-if.html
- Basis-CSS herunterladen: dark-mode-demo-CSS-if.css
- JavaScript-Code herunterladen: dark-mode-demo-CSS-if.js
Der Code im Head-Bereich
Wenn ein Nutzer für eine Seite deiner Website den Dunkelmodus wählt, wird erwartet, dass er auch für andere Seiten deiner Website den Dunkelmodus bevorzugt. Daher ist das JavaScript so eingerichtet, dass die Nutzerpräferenz im Local Storage des Browsers gespeichert wird.
Wir möchten ein Aufblitzen des Hellmodus vermeiden, bevor der gewünschte Dunkelmodus geladen oder aktualisiert wird (oder umgekehrt ein Aufblitzen des Dunkelmodus, bevor der gewünschte Hellmodus geladen wird). Das erreichen wir durch folgende Maßnahmen:
- Einfügen eines kleinen
<style>-Abschnitts vor dem Laden von CSS- oder JavaScript-Dateien, der eine CSS-Variable im:rootder Webseite definiert und gleichzeitig festlegt, dass dascolor-schemeder Seite den Wert dieser Variable verwendet. Der Standardwert folgt der systemseitigen Einstellung für Hell- oder Dunkelmodus. - Einfügen eines kleinen
<script>-Abschnitts, der den Wert dieser Modus-Variable entsprechend dem Local Storage des Browsers setzt.
Da der CSS-Code sofort auf das Dokument angewendet wird, noch bevor dem Nutzer etwas angezeigt wird, wird das korrekte color-scheme sofort übernommen – es gibt also kein unerwünschtes Aufblitzen von Hell- oder Dunkelmodus (vorausgesetzt, dass der Großteil der Farbänderungen durch die Methode light-dark() erfolgt). Es besteht kein Grund zur Sorge bezüglich der Performance, da der benötigte Code sehr klein ist. Der initiale Code im <head> fügt die Variable hinzu und setzt das color-scheme auf light dark:6
<meta name="color-scheme" content="light dark">
<style>
:root {
--DarkLight:light dark;
color-scheme: var(--DarkLight);
}
</style>
gefolgt von einem kleinen Skriptabschnitt:
<script>
let Gtheme = "system";
let GoverridesDL = false;
switch ((Gtheme = (Gtheme = localStorage.getItem('LStheme')) || 'system')) {
case 'system':
break;
case 'light':
document.documentElement.style.setProperty('--DarkLight', 'light');
if (window.matchMedia('(prefers-color-scheme: dark)').matches){
GoverridesDL = !GoverridesDL;
}
break;
case 'dark':
document.documentElement.style.setProperty('--DarkLight', 'dark');
if (window.matchMedia('(prefers-color-scheme: light)').matches){
GoverridesDL = !GoverridesDL;
}
}
</script>
Abschließend haben wir den Code, der das gesamte CSS durchsucht, alle prefers-color-scheme-Regeln findet und sie in einem Array speichert. Beachte, dass dabei auch prefers-color-scheme-Regeln innerhalb eines <style>-Tags im HTML-Dokument erfasst werden.
function* visitCssRule(cssRule) {
try{
// visit imported stylesheet
if (cssRule.type == cssRule.IMPORT_RULE) {
yield* visitStyleSheet(cssRule.styleSheet);
}
// yield media rule
if (cssRule.type == cssRule.MEDIA_RULE) {
// See if it is a prefers-color-scheme rule, ignore all whitespace
if (removeWhiteSpace(cssRule.media.mediaText) === '(prefers-color-scheme:dark)' || removeWhiteSpace(cssRule.media.mediaText) === '(prefers-color-scheme:light)' ){
yield cssRule;
}
}
} catch (e) {
// console.log(e + ' line: ' + e.lineNumber + ' File: ' + e.fileName);
}
}
function* visitStyleSheet(styleSheet) {
try {
// visit every rule in the stylesheet
let cssRules = styleSheet.cssRules;
for (let i = 0, cssRule; cssRule = cssRules[i]; i++) {
yield* visitCssRule(cssRule);
}
} catch (e) {
// console.log(e + ' line: ' + e.lineNumber + ' File: ' + e.fileName);
}
}
function* findDarkLightRules() {
try{
// visit all stylesheets
let styleSheets = document.styleSheets;
for (let i = 0, styleSheet; styleSheet = styleSheets[i]; i++) {
yield* visitStyleSheet(styleSheet);
}
} catch (e) {
// console.log(e + ' line: ' + e.lineNumber + ' File: ' + e.fileName);
}
}
function removeWhiteSpace (myString) {
return myString.replace(/\s/g, '');
}
2-Wege-Schalter vs. 3-Wege-Schalter
Diese Implementierung zum Umschalten zwischen Dunkel-/
Die überwiegende Mehrheit der Nutzer verwendet jedoch eine feste System-Einstellung – entweder Hell oder Dunkel. Das bedeutet, dass diese Nutzer keinen Unterschied bemerken, wenn der 2-Wege-Schalter auf Dunkel gestellt ist und auch die System-Einstellung Dunkel ist, oder wenn der Schalter auf Hell steht und auch die System-Einstellung Hell ist. Der erwähnte Leser argumentierte, dass einige Nutzer je nach Tageszeit zwischen Hell- und Dunkelmodus wechseln. Ich bin jedoch der Meinung, dass die Einfachheit und Kompaktheit des 2-Wege-Schalters für die meisten Nutzer vorzuziehen ist – solange es eine Option gibt, zur System-Einstellung zurückzukehren, wird jeder Anwendungsfall abgedeckt. Auf meiner eigenen Website habe ich jetzt eine Nachricht eingebaut, die den Nutzer daran erinnert, dass es eine Option gibt, auf die System-Einstellung zurückzusetzen. Diese Nachricht wird nur bei den ersten beiden Änderungen des Dunkel-/id DarkMsg erforderlich, das die Nachricht enthält. Die JavaScript-Funktion switchTheme wird entsprechend angepasst und enthält zusätzlich eine neue Funktion fadeOutEffect. Wer dies implementieren möchte, findet die Demo und die Dateien auf der Seite Einfache Dunkelmodus-Demo mit Rücksetz-Nachricht.
Abschließend…
Wie oben erwähnt, kannst du eine Demo der wesentlichen Dateien auf der einfachen Dunkelmodus-Demo-Seite ansehen – die Download-Links findest du oben (Download-Links).
Beachte, dass du überprüfen solltest, wie deine Webseiten in der Druckvorschau aussehen, wenn du bei aktivem Dunkelmodus auf „Drucken“ klickst, da es zu unerwarteten Effekten kommen kann.
Fußnoten
(1) Möglicherweise kannst du einen sicheren Fallback einbauen, indem du vor der Zwei-Farb-Deklaration eine einzelne Farbangabe machst – so wird bei fehlender Unterstützung der Zwei-Farb-Deklaration wenigstens die Einzelfarbe angewendet. Diese Möglichkeit wird hier jedoch nicht behandelt.
(2) Beachte, dass die light-dark-Methode selbst eine Bedingung ist – allerdings mit eingeschränkten Parametern.
(3) Beachte, dass du bei bestimmten Elementen eine Farbe auf transparent setzen kannst, um das Element für den Nutzer unsichtbar zu machen – allerdings belegt es weiterhin Platz auf dem Bildschirm, z. B. bei Rahmen.
(4) Beachte, dass die CSS-Datei nicht verändert wird – es wird lediglich die im Speicher gehaltene Information angepasst.
(5) Du kannst sogar sowohl prefers-color-scheme: dark als auch prefers-color-scheme: light in deinem Code verwenden – besser ist es jedoch, dies zu vermeiden, da das CSS sonst schwerer zu warten ist (siehe Beispiel auf meiner Demo-Seite). Beachte auch, dass der Code nicht auf prefers-color-scheme-Regeln in CSS-Dateien von externen Domains zugreifen kann, außer du ergänzt zusätzlichen Code – siehe z. B. https://stackoverflow.com/questions/71327187/cannot-access-cssrules-for-stylesheet-cors.
(6) Das <meta name="color-scheme" content="light dark"> ist nicht zwingend erforderlich, wird aber empfohlen – siehe MDN Web Docs: color-scheme.
Letzte Änderung am Aktualisiert am: 18.10.2025