Komm auf die hell-dunkel Seite!
Übersetzung von "Come to the light-dark side!" von Sara Joy auf CSS Tricks.
Es ist verständlich, wenn Sie annehmen, dass die gleichzeitige Programmierung eines Dunkel- und eines Hellmodus viel Arbeit bedeutet. Sie müssen @media‑Abfragen basierend auf prefers‑color‑scheme im Kopf behalten sowie zusätzliche Komplikationen berücksichtigen, wenn Sie Besucher wählen lassen wollen, ob sie einen Hell‑ oder Dunkelmodus getrennt von der Betriebssystem‑Einstellung wünschen. Und vergessen wir nicht die Farbpalette selbst! Der Wechsel von einem „Hellmodus“ zu einem „Dunkelmodus“ kann neue Farbvariationen erfordern, um den richtigen Kontrast für ein barrierefreies Erlebnis zu erzielen.
Es ist in der Tat viel Arbeit. Aber ich bin hier, um Ihnen zu sagen: Es ist jetzt viel einfacher mit modernem CSS!
Standard‑HTML‑Farbschema(e)
Wir alle kennen das „nackte“ HTML‑Theme, auch wenn wir es selten so sehen, da wir bereits vor dem Öffnen von localhost ein CSS‑Reset oder unser Lieblings‑Boilerplate‑CSS angewendet haben. Aber hier ist eine Neuigkeit: HTML hat nicht nur das standardmäßige Schwarz‑auf‑Weiß‑Theme, es gibt auch eine native Weiß‑auf‑Schwarz‑Version.
Wenn Sie eine Dunkelmodus‑Schnittstelle erstellen möchten, ist dies eine großartige Basis und erspart Ihnen, lästige Details berücksichtigen zu müssen, wie beispielsweise dunkle Eingabefelder, Buttons und andere interaktive Elemente.
Automatisches Wechseln der Farbschemata basierend auf der OS‑Präferenz
Ohne jegliche @media‑Abfragen — oder überhaupt irgendein zusätzliches CSS — wenn wir einfach nur color‑scheme: light dark auf dem Wurzelelement deklarieren, wird die Seite automatisch entweder das Hell‑ oder das Dunkelschema anwenden, indem sie sich nach den Betriebssystempräferenzen des Besuchers richtet. Die meisten Betriebssysteme haben eine eingebaute Barrierefreiheits‑Einstellung für Ihr bevorzugtes Farbschema — „light“, „dark“ oder sogar „auto“ — und Browser respektieren diese Einstellung.
html { color‑scheme: light dark; }
Wir können dies sogar ohne direktes CSS im HTML‑Dokument in einem <meta>‑Tag erreichen:
<meta name="color‑scheme" content="light dark">
Ob Sie nun den CSS‑ oder den HTML‑Weg wählen — es spielt keine Rolle: Beide funktionieren auf die gleiche Weise: Sie weisen den Browser an, sowohl Hell‑ als auch Dunkelschemata verfügbar zu machen und dasjenige anzuwenden, das zur Präferenz des Besuchers passt. Wir müssen nicht einmal unsere Styles mit prefers‑color‑scheme übersähen, nur um Farben auszutauschen, weil die Logik bereits eingebaut ist!
Sie können den Werten light oder dark die Eigenschaft color‑scheme zuweisen. Gleichzeitig würde ich sagen, dass die Setzung von color‑scheme: light redundant ist, da dies das Standardfarbschema ist — mit oder ohne Deklaration.
Sie können natürlich mit JavaScript das <meta>‑Tag oder die CSS‑Eigenschaft steuern.
Es gibt auch die Möglichkeit, die color‑scheme Eigenschaft auf bestimmten Elementen anzuwenden statt auf der gesamten Seite. Allerdings heißt das dann, dass Sie explizit die color und background‑color Eigenschaften des Elements deklarieren müssen; andernfalls ist das Element transparent und erbt seine Textfarbe vom Elternelement.
Welche Werte sollten Sie ihm geben? Versuchen Sie:
Standard‑Text‑ und Hintergrundfarben‑Variablen
Die „schwarzen“ Farben dieser nativen Themes sind nicht immer vollständig schwarz, sondern oft fast‑schwarz, wodurch der Kontrast fürs Auge etwas angenehmer ist. Es lohnt sich auch zu erwähnen, dass es Unterschiede in der „Schwärze“ von „schwarz“ zwischen Browsern gibt.
Sehr nützlich ist, dass diese standardmäßig nicht‑reinen Schwarz‑ und eventuell nicht‑reinen Weiß‑Werte von background‑color und Text‑color als <system‑color> Variablen verfügbar sind. Sie drehen automatisch ihre Farbwerte mit color‑scheme mit!
Diese sind: Canvas und CanvasText.
Diese beiden Variablen können überall in Ihrem CSS verwendet werden, um die aktuelle Standard‑Hintergrundfarbe (Canvas) oder Textfarbe (CanvasText) basierend auf dem aktuellen Farbschema abzurufen. Wenn Sie mit der CSS‑Wert‑Notation currentColor vertraut sind, scheint es ähnlich zu funktionieren. CanvasText wiederum bleibt die Standardtext‑color, insofern als sie nicht geändert werden kann wie currentColor, wenn Sie etwas dem color zuweisen.
In den folgenden Beispielen ist die einzige Änderung die color‑scheme‑Eigenschaft:


Nicht schlecht! Es gibt ganz viele dieser System‑Variablen. Sie sind nicht case‑sensitive, oft geschrieben in camelCase oder PascalCase zur Lesbarkeit. MDN zählt 19 <system‑color> Variablen auf, und ich liste sie unten zur Referenz auf.
Öffnen, um die 19 System‑Farbnamen und Beschreibungen zu sehen
AccentColor: Die Hintergrundfarbe für akzentuierte Interface‑KontrollenAccentColorText: Die Textfarbe für akzentuierte Interface‑KontrollenActiveText: Die Textfarbe aktiver LinksButtonBorder: Die Grund‑Randfarbe für KontrollenButtonFace: Die Hintergrundfarbe für KontrollenButtonText: Die Textfarbe für KontrollenCanvas: Die Hintergrundfarbe der Inhalte oder Dokumente einer AnwendungCanvasText: Die im Inhalt oder in Dokumenten einer Anwendung verwendete TextfarbeField: Die Hintergrundfarbe für EingabefelderFieldText: Die Textfarbe in Form‑EingabefeldernGrayText: Die Textfarbe für deaktivierte Elemente (z. B. eine deaktivierte Kontrolle)Highlight: Die Hintergrundfarbe für ausgewählte ElementeHighlightText: Die Textfarbe für ausgewählte ElementeLinkText: Die Textfarbe für nicht‑aktive, nicht besuchte LinksMark: Die Hintergrundfarbe für Text, der in einem<mark>Element markiert istMarkText: Die Textfarbe für Text, der in einem<mark>Element markiert istSelectedItem: Die Hintergrundfarbe für ausgewählte Elemente (z. B. ein ausgewähltes Kontrollkästchen)SelectedItemText: Die Textfarbe für ausgewählte ElementeVisitedText: Die Textfarbe besuchter Links
Cool, oder? Es gibt davon ganz viele! Leider gibt es auch Unterschiede darin, wie diese Farbschlüssel zwischen verschiedenen Betriebssystemen und Browsern verwendet und gerendert werden. Auch wenn „„evergreen“ Browser wahrscheinlich alle unterstützen, sind sie nicht alle wirklich kompatibel und können die CSS-Eigenschaft „colorscheme“ nicht wie vorgesehen umschalten.
Egor Kloos (auch bekannt als dutchcelt) behält den aktuellen Status der Systemfarben im Auge, darunter welche Farben es gibt und welche Browser sie unterstützen. Dies tut er im Rahmen eines klassenlosen CSS-Frameworks mit dem cleveren Namen system.css.
Farben für beide Modi gemeinsam deklarieren
Gut, jetzt haben Sie also eine Seite, die sich automatisch je nach Systempräferenz zwischen Hell‑ und Dunkelmodus umschaltet. Ob Sie nun diese Systemfarben verwenden oder nicht, bleibt Ihnen überlassen. Ich möchte nur darauf hinweisen, dass „Dunkel“ nicht immer „reines Schwarz“ bedeuten muss, ebenso wenig wie „Hell“ unbedingt „reines Weiß“ heißen muss. Es gibt viele weitere Farben, die kombiniert werden können!
Aber was ist der beste oder einfachste Weg, Farben so zu deklarieren, dass sie in beiden Modi funktionieren?
In meiner subjektiven umgekehrten „Bestenreihenfolge“:
Platz 3: Farb‑Opacity deklarieren
Sie könnten sämtliche Hintergrundfarben im Dunkel‑ und Hellmodus gleich behalten, aber sie mit einer Transparenz deklarieren (z. B. rgb(128 0 0 / 0.5) oder #80000080). Dann wird die Canvas‑Farbe durchscheinen.
Für Textfarben ist das so nicht brauchbar, und Sie landen möglicherweise bei etwas „gedämpften“ Farben. Aber es ist eine einfache Möglichkeit, schnell ein Theming zu erledigen. Das habe ich für die Codeblöcke in dieser alten Hell‑ und Dunkelmodus‑Demo gemacht.

Platz 2: Verwendung von color‑mix()
So etwa:
color‑mix(in oklab, Canvas 75%, RebeccaPurple);
Ähnlich (aber auch anders) als die Verwendung von Transparenz zur Farbdämpfung ist das Farbenmischen in CSS. Wir können sogar die System‑Farbvariablen mischen! Zum Beispiel kann eine der Farben entweder Canvas oder CanvasText sein, sodass die Hintergrundfarbe immer mit Canvas gemischt wird und die Textfarbe immer mit CanvasText.
Wir haben jetzt die CSS‑Funktion color‑mix() zur Hilfe. Das erste Argument der Funktion definiert den Farbraum, in dem das Mischen stattfindet. Zum Beispiel können wir der Funktion sagen, dass wir im OKLAB‑Farbraum arbeiten, der ein rechteckiger Farbraum wie sRGB ist und sich daher ideal für das Mischen mit sRGB‑Farbwerten eignet für vorhersehbare Ergebnisse. Sie können Farben durchaus aus verschiedenen Farbräumen mischen — die Kombination OKLAB/sRGB funktioniert für mich in diesem Fall.
Das zweite und dritte Argument sind die Farben, die Sie mischen möchten, und in welchem Verhältnis. Verhältnisse sind optional, werden aber prozentual ausgedrückt. Ohne Angabe eines Verhältnisses erfolgt die Mischung gleichmäßig (50 %‑50 %). Wenn Sie Prozentsätze für beide Farben angeben und sie nicht 100 % ergeben, rechnet die Funktion ein wenig nach, um Fehler zu vermeiden.
Der color‑mix() Ansatz ist nützlich, wenn Sie gerne dieselben Farb‑Töne und Sättigungen beibehalten möchten, unabhängig davon ob der Modus Hell oder Dunkel ist.

In diesem Beispiel sehen Sie, wie beim Verändern des Hue‑Sliders Farbänderungen in den thematischen Boxen sichtbar werden, die dem Thema folgen, aber mit Canvas und CanvasText gemischt sind:
Vielleicht haben Sie bemerkt, dass ich im letzten Beispiel OKLCH und HSL Farbräume verwendet habe. Vielleicht haben Sie auch bemerkt, dass das HSL‑basierte Theme und der thematische Absatz viel „auffälliger“ waren, als Sie den Hue‑Slider bewegten.
Ich habe jahrelang Farben mit einem polaren Farbraum wie HSL deklariert, und liebte es, dass man leicht einen Farbton nehmen und Sättigung und Helligkeit nach Bedarf hoch oder runterziehen kann. Aber ich gestehe, dass es problematisch sein kann, wenn man mit mehreren Farbtönen arbeitet und versucht, über alle hinweg konsistente wahrgenommene Helligkeit und Sättigung zu erreichen. Es kann schwierig sein, genug Kontrast über ein Spektrum von Farben mit HSL bereitzustellen.
Der OKLCH Farbraum ist ebenfalls polar genau wie HSL, mit denselben Vorteilen. Sie können Ihren Farbton wählen und den Chroma‑Wert (der ein wenig wie Sättigung in HSL ist) und die Helligkeitsskalen präzise verwenden. Sowohl OKLCH als auch OKLAB sind so ausgelegt, dass sie das, was unsere Augen in Bezug auf Helligkeit und Farbe wahrnehmen, besser widerspiegeln, im Vergleich zum Übergang zwischen Farben im sRGB‑Raum.
Während diese Farbräume nicht unbedingt die uralte Frage beantworten, Ist mein Blau dasselbe wie Dein Blau?
so sind die Farben viel konsistenter und erfordern weniger „Feintuning“, wenn Sie die gesamte Farbpalette Ihrer Website auf eine andere Themenfarbe umstellen. Mit diesen Farbräumen bleibt der Kontrast zwischen den berechneten Farben ziemlich gleich.
Platz 1 (Gewinner!): Verwendung von light‑dark()
So:
light‑dark(lavender, saddlebrown);
Im vorherigen color‑mix() Beispiel, wenn Sie einen blassen Lavendel im Hellmodus wählen, ergibt sich sein Gegenstück im Dunkelmodus als sehr dunkler Lavendel.
Die light‑dark() Funktion hingegen bietet vollständige Kontrolle. Sie könnten möchten, dass dieses Element im Hellmodus blasser Lavendel ist und im Dunkelmodus ein tiefes verbranntes Sienabraun wird. Warum nicht? Sie können innerhalb von light‑dark() weiterhin color‑mix() verwenden, wenn Sie wollen — deklarieren Sie die Farben wie Sie möchten und gewinnen Sie viel feinere Kontrolle über Ihre Farben.
Experimentieren Sie gerne in der folgenden editierbaren Demo:
Die Nutzung von color‑scheme: light dark; — oder das entsprechende Meta‑Tag im HTML Ihrer Seite — ist eine Voraussetzung für die Funktion light‑dark(), denn sie erlaubt der Funktion, die System‑Präferenz einer Person zu respektieren oder welchen einzelnen light‑ oder dark‑Wert Sie auf color‑scheme gesetzt haben.
Eine weitere Überlegung: light‑dark() ist neu(er) in Browsern verfügbar, mit knapp über 80 % Unterstützung unter allen Nutzern zum Zeitpunkt dieses Schreibens. Also sollten Sie eventuell ein Fallback in Ihrem CSS vorsehen für Browser, die die Funktion nicht unterstützen.
Warum ist die Nutzung von color‑scheme und light‑dark() besser als die Nutzung von @media‑Abfragen?
@media‑Abfragen waren exzellente Werkzeuge, aber sie werden zur Abfrage von prefers‑color‑scheme nur immer der Präferenz folgen, die auf dem Betriebssystem der Person eingestellt ist. Das ist in Ordnung – bis Sie (zu Recht) dem Besucher mehr Wahlmöglichkeiten anbieten möchten, entkoppelt davon, ob er die UI seines Geräts lieber dunkel oder hell haben möchte.
Wir können das natürlich schon – wir sind gewohnt an allerlei Tricks mit zusätzlichen CSS‑Klassen, duplizierten Styles oder der Verwendung von Custom‑Properties, um es möglich zu machen.
Die Freude an der Nutzung von color‑scheme zeigt sich in dreifacher Form:
- Es gibt Ihnen den grundlegenden monochromen Dunkelmodus kostenlos dazu!
- Es kann nativ den Moduswechsel basierend auf der OS‑Modus‑Präferenz übernehmen.
- Sie können JavaScript verwenden, um zwischen Hell‑ und Dunkelmodus umzuschalten, und die Farben, die in den
light‑dark()Funktionen deklariert sind, folgen dem Umschalter.
Hell, Dunkel und Auto Modus‑Steuerungen
Im Wesentlichen setzen wir einfach eine von drei Optionen dafür, ob das color‑scheme light, dark oder automatisch (also auto) sein soll.
Ich empfehle, alle drei als getrennte Optionen anzubieten, da dies einige Komplikationen für Sie beseitigt! Jeder neue Besucher der Seite wird wahrscheinlich im auto‑Modus sein, weil das Akzeptieren der Betriebssystem‑Einstellung des Besuchers der am wenigsten störende Standardzustand ist. Dann geben Sie dieser Person die Wahl, dabei zu bleiben oder ein anderes Farbschema auszuwählen. Auf diese Weise müssen Sie nicht herausfinden, welchen Modus jemand bevorzugt, z. B. um das richtige Icon bei einem Umschalter anzuzeigen und die korrekte Aktion auszulösen. Es gibt auch keinen Bedarf, einen Event‑Listener auf prefers‑color‑scheme abzuhören im Falle von Änderungen – Ihre Deklaration color‑scheme: light dark im CSS übernimmt das für Sie.

Anpassung des color‑scheme in reinem CSS
Ja, das ist völlig möglich! Aber der Ansatz kommt mit ein paar Vorbehalten:
- Sie können kein
<button>verwenden – nur Radio‑Inputs oder<option>in einem<select>Element. - Es funktioniert nur pro Seite, nicht pro Website, d. h. Änderungen gehen bei Reload oder Aktualisierung verloren.
- Der Browser muss den :
has()Pseudo‑Selektor unterstützen. Die meisten modernen Browser tun es, aber manche Nutzer mit älteren Geräten könnten aussteigen.
Verwendung des :has() Pseudo‑Selectors
Dieser Ansatz ist fast alarmierend einfach und ist fantastisch für eine einfache One‑Pager! Der Großteil der Arbeit wird mit diesem erledigt:
/* default, oder 'auto' */ html { color‑scheme: light dark; } html:has([value="light"]:checked) { color‑scheme: light; } html:has([value="dark"]:checked) { color‑scheme: dark; }
Die zweite und dritte Regel suchen nach einem Attribut namens value auf einem Element, das „light“ oder „dark“ zugewiesen hat, und ändern das color‑scheme nur wenn dieses Element :checked ist.
Dieser Ansatz ist nicht sehr effizient, wenn Sie eine riesige Seite voller Elemente haben. In solchen Fällen ist es besser, präziser zu sein. In den folgenden zwei Beispielen prüfen die CSS‑Selektoren das value nur innerhalb eines Elements, das id="mode‑switcher" enthält.
html:has(#mode‑switcher [value="light"]:checked) { color‑scheme: light } /* Wussten Sie, dass Sie das „;“ bei einer Einzeiler nicht brauchen? Jetzt wissen Sie es! */
Verwendung eines <select> Elements:
Verwendung von <input type="radio">:
Theoretisch könnten wir auch Kontrollkästchen dafür verwenden, aber da Kontrollkästchen nicht dazu gedacht sind, mutually exclusive (gegenseitig ausschließende) Optionen zu sein, werde ich hier kein Beispiel liefern. Was passiert, wenn mehr als eine Option ausgewählt ist? Die letzte passende CSS‑Deklaration gewinnt (was im obigen Beispiel dark wäre).
Anpassung des color‑scheme in HTML mit JavaScript
Ich halte mich an Jeremy Keith’s Maxim, wenn es darum geht, JavaScript zu nutzen:
JavaScript sollte nur tun, was nur JavaScript tun kann.
Genau das ist hier der Fall.
Wenn Sie Besuchern erlauben möchten, das Farbschema mit Buttons zu ändern, oder die Option beim nächsten Besuch gespeichert sein soll, dann benötigen wir zumindest etwas JavaScript. Anstatt den :has() Pseudo‑Selektor in CSS zu verwenden, haben wir ein paar alternative Ansätze zur Änderung des color‑scheme, wenn wir JavaScript einmischen.
Nutzung von <meta>‑Tags
Wenn Sie Ihr color‑scheme innerhalb eines Meta‑Tags im <head> Ihres HTML gesetzt haben:
<meta name="color‑scheme" content="light dark">
… könnten Sie mit einer nützlichen Konstante starten, so:
const colorScheme = document.querySelector('meta[name="color‑scheme"]');
Und dann können Sie diese manipulieren und ihr light oder dark zuweisen, wie Sie es wünschen:
colorScheme.setAttribute("content", "light"); // für Hellmodus
colorScheme.setAttribute("content", "dark"); // für Dunkelmodus
colorScheme.setAttribute("content", "light dark"); // für Auto‑Modus
Das ist ein sehr ähnlicher Ansatz zur Nutzung von <meta> Tags, unterscheidet sich allerdings, wenn Sie das color‑scheme in CSS setzen:
html { color‑scheme: light dark; }
Anstatt eine Konstante colorScheme wie im letzten Beispiel mit dem <meta> Tag zu verwenden, könnten Sie stattdessen das <html> Element selektieren:
const html = document.querySelector('html');
Nun sehen Ihre Manipulationen so aus:
html.style.setProperty("color‑scheme", "light"); // für Hellmodus
html.style.setProperty("color‑scheme", "dark"); // für Dunkelmodus
html.style.setProperty("color‑scheme", "light dark"); // für Auto‑Modus
Ich setze solche Manipulationen gerne in Funktionen um, damit ich sie wiederverwenden kann:
function switchAuto() { html.style.setProperty("color‑scheme", "light dark"); }
function switchLight() { html.style.setProperty("color‑scheme", "light"); }
function switchDark() { html.style.setProperty("color‑scheme", "dark"); }
Alternativ möchten Sie vielleicht so DRY (Don’t Repeat Yourself) wie möglich bleiben und so etwas tun:
function switchMode(mode) { html.style.setProperty("color‑scheme", mode === "auto" ? "light dark" : mode); }
Die folgende Demo zeigt, wie dieser JavaScript‑basierte Ansatz mit Buttons, Radio‑Buttons und einem <select> Element verwendet werden kann. Bitte beachten Sie, dass nicht alle Steuerungen im UI tatsächlich verbunden sind – die Demo wäre sonst zu kompliziert, da es keine Welt gibt, in der alle drei Typen von Steuerungen gleichzeitig verwendet werden!
Ich entschied mich dafür, onchange und onclick in den HTML‑Elementen einzusetzen, hauptsächlich weil ich sie lesbar und ordentlich finde. Es spricht nichts dagegen, stattdessen einen Change‑Event‑Listener an Ihre Steuerungen zu hängen, insbesondere wenn Sie andere Aktionen auslösen müssen, wenn sich die Optionen ändern. Die Verwendung von onclick auf einem Button funktioniert nicht nur für Klicks – der Button ist weiterhin tastatur‑fokussierbar und kann wie üblich mit Leertaste und Enter ausgelöst werden.
Auswahl merken für wiederholte Besuche
Die größte Einschränkung bei allem bisher Gesehenen ist, dass dies nur einmal funktioniert. Anders gesagt: Sobald der Besucher die Seite verlässt, tun wir nichts, um seine Farbschema‑Präferenz zu merken. Es wäre eine bessere Nutzererfahrung, diese Präferenz zu speichern und sie jederzeit zu respektieren, wenn der Besucher zurückkommt.
Die Web Storage API ist unsere erste Wahl dafür. Und es gibt zwei verfügbare Wege, die Farbschema‑Präferenz einer Person für zukünftige Besuche zu speichern.
localStorage
LocalStorage speichert Werte direkt auf dem Gerät des Besuchers. Das macht es zu einer schönen Möglichkeit, Dinge vom Server fernzuhalten, da die gespeicherten Daten nie ablaufen und jederzeit abrufbar sind. Allerdings sind wir anfällig dafür, diese Daten zu verlieren, wenn der Besucher Cookies und Cache löscht – dann muss er eine neue Auswahl treffen, die erneut in localStorage gespeichert wird.
Sie wählen einen Schlüssel‑Namen und vergeben einen Wert mit .setItem():
localStorage.setItem("mode", "dark");
Der Schlüssel und Wert werden vom Browser gespeichert und können bei zukünftigen Besuchen abgerufen werden:
const mode = localStorage.getItem("mode");
Dann können Sie den gespeicherten Wert dieses Schlüssels verwenden, um das bevorzugte Farbschema der Person anzuwenden.
sessionStorage
SessionStorage wird verworfen, sobald ein Besucher auf eine andere Website wechselt oder das aktuelle Fenster/Tab schließt. Allerdings bleiben die Daten, die wir in sessionStorage erfassen, erhalten, während der Besucher zwischen Seiten oder Ansichten auf derselben Domain navigiert.
Es sieht sehr ähnlich aus wie localStorage:
sessionStorage.setItem("mode", "dark");
const mode = sessionStorage.getItem("mode");
Welche Speichermethode sollte ich verwenden?
Persönlich habe ich mit sessionStorage gestartet, weil ich meine Seite so einfach wie möglich halten wollte und vermeiden wollte, etwas zu verwenden, das ein GDPR‑konformes Cookie‑Banner erforderlich machen würde, falls wir die Präferenz der Person über deren Sitzung hinaus speichern. Wenn der Großteil Ihres Traffics von neuen Besuchern kommt, dann empfehle ich sessionStorage, um weniger Arbeit auf der GDPR‑Seite zu haben.
Wenn Ihr Traffic jedoch hauptsächlich aus wiederkehrenden Besuchern besteht, dann ist localStorage wahrscheinlich die bessere Wahl. Der Komfort für Ihre Besucher rechtfertigt dann die GDPR‑Arbeit.
Das folgende Beispiel zeigt den localStorage Ansatz. Öffnen Sie es in einem neuen Fenster oder Tab, wählen Sie ein Thema, das anders ist als die Präferenz Ihres Betriebssystems, schließen Sie das Fenster oder Tab und öffnen Sie die Demo erneut in einem neuen Fenster oder Tab. Respektiert die Demo das Farbschema, das Sie ausgewählt haben? Es sollte!
Wählen Sie die „Auto“‑Option, um wieder zur Normalität zurückzukehren.
Wenn Sie genauer sehen möchten, was vor sich geht, können Sie die Entwickler‑Tools Ihres Browsers öffnen (F12 für Windows, STRG + Klick und „Untersuchen“ wählen für macOS). Gehen Sie dort in den Reiter „Application“ und suchen Sie https://cdpn.io in der Liste der im localStorage gespeicherten Items. Sie sollten den gespeicherten Schlüssel (mode) und den Wert (dark oder light) sehen. Dann beginnen Sie erneut, auf die Farbschema‑Optionen zu klicken und beobachten Sie in Echtzeit, wie sich der mode aktualisiert.

Barrierefreiheit
Herzlichen Glückwunsch! Wenn Sie es bis hierhin geschafft haben, erwägen Sie bereits oder stellen Sie schon Versionen Ihrer Website zur Verfügung, die für verschiedene Menschen angenehmer zu benutzen sind.
Zum Beispiel:
- Menschen mit stark sichtbaren „Floaters“ in ihren Augen bevorzugen vielleicht den Dunkelmodus.
- Menschen mit Astigmatismus können möglicherweise im Hellmodus leichter fokussieren.
Das Bereitstellen beider Versionen führt dazu, dass weniger Menschen ihre Augen anstrengen müssen, um auf die Inhalte zuzugreifen.
Kontraststufen
Ich möchte eine kleine Ergänzung zu diesem Angebot eines Hell‑ und Dunkelmodus machen. Eine einfache Versuchung ist es, vollständig monochromes Schwarz‑auf‑Weiß oder Weiß‑auf‑Schwarz anzubieten. Es ist eindrucksvoll und prägnant! Ich verstehe das. Aber genau das – eindrucksvoll und prägnant – kann bei einigen Menschen, die anfällig für Migräne sind, auch einen Trigger darstellen, und sie kommen mit niedrigeren Kontrasten besser zurecht.
Einen hohen Kontrast bereitzustellen ist großartig für Menschen, die ihn brauchen. Manche Seh‑Behinderungen machen es unmöglich, einen scharfen Eindruck zu gewinnen, und ein hoher Kontrast kann Menschen helfen, Wortformen trotz Unschärfe besser zu erkennen. Minimum‑Kontraststufen sind wichtig und sollten überschritten werden.
Glücklicherweise können wir neben anderen Media‑Queries auch prefers‑contrast abfragen, welches Werte für no‑preference, more, less oder custom akzeptiert.
Im folgenden Beispiel (welches :has() und color‑mix() verwendet), wird ein <select> Element angezeigt, das Kontrasteinstellungen anbietet. Wenn „Low“ ausgewählt ist, wird ein Filter von contrast(75%) über die Seite gelegt. Wenn „High“ ausgewählt ist, werden CanvasText und Canvas ungemischt für Textfarbe und Hintergrundfarbe verwendet:
Durch das Hinzufügen eines schnellen Hoch‑ und Niedrig‑Kontrast‑Themes geben Sie Ihren Besuchern noch mehr Wahlmöglichkeiten für ihren Lesekomfort. Sehen Sie – jetzt haben Sie drei Kontraststufen sowohl im Dunkel‑ als auch im Hellmodus – sechs Farbschemata zur Auswahl!
ARIA‑pressed
ARIA steht für „Accessible Rich Internet Applications“ und ist dafür gedacht, ein bisschen zusätzliche Information wenn nötig für Screen‑Reader und andere unterstützende Technologien hinzuzufügen.
Die Worte „wenn nötig“ tragen hier viel Gewicht. Es wird gesagt, dass – wie Apostrophe – kein ARIA besser ist als schlechtes ARIA. Also: Best‑Practice ist es, es nicht überall hineinzupflanzen. In den meisten Fällen (mit wenigen Ausnahmen) sind native HTML‑Elemente out‑of‑the‑box gut – insbesondere, wenn Sie nützliche Texte in Ihren Buttons haben!
Der kleine Teil von ARIA, den ich in dieser Demo verwende, dient dazu, das aria‑pressed Attribut zu den Buttons hinzuzufügen, denn anders als bei einer Radio‑Gruppe oder einem Select‑Element ist ansonsten nicht klar, welcher Button „aktiv“ ist. ARIA hilft hier schön. Nun wird ein Screen‑Reader sowohl seinen zugänglichen Namen als auch ob er im gedrückten oder nicht gedrückten Zustand ist, zusammen mit einem Button ankündigen.
Im Folgenden ein Code‑Snippet mit dem gesamten ARIA‑Code fett markiert — ja, plötzlich gibt es viel mehr! Sie finden vielleicht elegantere (oder DRY‑ere) Wege, dies zu tun, aber die Darstellung auf diese Weise macht zunächst deutlicher, was passiert.
Unsere Buttons haben ids, die wir verwendet haben, um sie mit ein paar weiteren nützlichen consts oben anzusprechen. Jedes Mal, wenn wir den mode wechseln, machen wir den Button’s aria‑pressed Wert für den ausgewählten Modus auf true, und die anderen beiden auf false:
const html = document.querySelector("html");
const mode = localStorage.getItem("mode");
const lightSwitch = document.querySelector('#lightSwitch');
const darkSwitch = document.querySelector('#darkSwitch');
const autoSwitch = document.querySelector('#autoSwitch');
if (mode === "light") switchLight();
if (mode === "dark") switchDark();
function switchAuto() { html.style.setProperty("color‑scheme", "light dark"); localStorage.removeItem("mode"); lightSwitch.setAttribute("aria‑pressed","false"); darkSwitch.setAttribute("aria‑pressed","false"); autoSwitch.setAttribute("aria‑pressed","true"); }
function switchLight() { html.style.setProperty("color‑scheme", "light"); localStorage.setItem("mode", "light"); lightSwitch.setAttribute("aria‑pressed","true"); darkSwitch.setAttribute("aria‑pressed","false"); autoSwitch.setAttribute("aria‑pressed","false"); }
function switchDark() { html.style.setProperty("color‑scheme", "dark"); localStorage.setItem("mode", "dark"); lightSwitch.setAttribute("aria‑pressed","false"); darkSwitch.setAttribute("aria‑pressed","true"); autoSwitch.setAttribute("aria‑pressed","false"); }
Beim Laden haben die Buttons einen Standard‑Zustand, nämlich wenn der „Auto“‑Modus‑Button aktiv ist. Sollte im localStorage bereits ein anderer Modus sein, greifen wir sofort zu und führen entweder switchLight() oder switchDark() aus – beide enthalten die aria‑pressed Änderungen, die relevant für diesen Modus sind.
<button id="autoSwitch" aria‑pressed="true" type="button" onclick="switchAuto()">Auto</button><button id="lightSwitch" aria‑pressed="false" type="button" onclick="switchLight()">Light</button><button id="darkSwitch" aria‑pressed="false" type="button" onclick="switchDark()">Dark</button>
Der letzte Vorteil von aria‑pressed ist, dass wir ihn auch für Stil‑Zwecke targetieren können:
button[aria‑pressed="true"] { background‑color: transparent; border‑width: 2px; }
Schließlich haben wir einen hübschen kleinen Button‑Umschalter, mit seinem Zustand klar angezeigt und angesagt, der Ihre Auswahl beim Rückkehrenden Besucher speichert. Fertig!
Ausführung / Schlusswort
Oder was auch immer das Gegenteil einer Einführung ist…
…lassen Sie sich nicht in die alte Diskussion Hell vs. Dunkelmodus hineinziehen. Beides ist gut. Beides ist großartig! Und beide Modi sind jetzt einfach gleichzeitig zu erstellen. Am Anfang Ihres nächsten Projekts, Ihrer Arbeit oder Ihres Hobbys: Geben Sie sich nicht der Angst hin und wählen Sie eine Seite – versuchen Sie beide, und geben Sie sich der Wahl hin.
Letzte Änderung am Aktualisiert am: 23.11.2025