Nativer Dark Mode mit CSS

Jeder kennt den Dark Mode via @media (prefers-color-scheme: dark), doch wusstet ihr, dass in CSS auch Support für einen nativen Dark Mode im Browser vorhanden ist? Der läuft über color-scheme und ist nicht nur deutlich einfacher umzusetzen, sondern liefert am Ende auch die bessere Performance.

Wie genau der native Dark Mode in CSS funktioniert, welche Optionen es bei color-scheme gibt und wie dies in Kombination mit @media (prefers-color-scheme: dark) sinnvoll umgesetzt werden kann, zeige ich euch im heutigen Beitrag. Für alle Puristen ist das nämlich die ideale Lösung.

Das ist auch einer der Gründe dafür, warum mir der native Dark Mode in CSS so sehr am Herzen liegt. Einfach deshalb, weil ich ein Freund von minimalistischen Designs bin, Brutalismus bei meinen Projekten bevorzuge und es demnach mag, wenn native Möglichkeiten voll ausgenutzt werden. Die sind am Ende nämlich meist effizienter als selbst gebaute Alternativen und gerade der native Dark Mode im Browser, der via CSS angesteuert wird, ist ein typisches Beispiel für eine einfache Lösung, die meist unnötig komplex realisiert wird. Doch schauen wir uns das genauer an.

Nativer Dark Mode CSS
Der native Dark Mode via CSS color-scheme funktioniert hauptsächlich bei einfachen Designs besonders gut, da er auf die User-Agent Stylesheet der Browser zurückgreift.

Dark Mode mit User-Agent Stylesheets

Es ist noch gar nicht so lange her, da ich habe ich einen ausführlichen Artikel zum Thema Brutalismus Design verfasst. In diesem Artikel hatte ich von den sogenannten User-Agent Stylesheets berichtet. Diese User-Agent Stylesheets sind Standard Designs, die im Browser bereits vorgegeben sind. Sie bilden die Grundlage für den Brutalismus, der sich weniger auf eine umfangreiche Gestaltung, als vielmehr auf ebendiese Standardwerte verlässt.

Texte sind also schwarz, Links sind blau und der Dark Mode wird nicht mittels @media (prefers-color-scheme: dark) realisiert, sondern mit dem CSS-Standard der Browser, nämlich color-scheme. Das erfordert weniger Code, keinen Query via CSS und vor allem auch weniger CSS-Klassen, die alle möglichen Farbwerte enthalten müssen, um den selbst gebauten Dark Mode entsprechend anzupassen.

Der CSS-Befehl color-scheme greift dabei auf die eben bereits erwähnten User-Agent Stylesheets zurück. Die wiederum geben an, wie der jeweilige Browser bestimmte CSS-Werte von Haus aus anzeigt und ausgibt. Für alles in CSS gibt es nämlich Standardwerte, dementsprechend auch für den Befehl color-scheme. Das wiederum heißt, ihr müsst keinen komplizierten Dark Mode via @media (prefers-color-scheme: dark) erstellen, da der Browser bereits einen Dark Mode enthält. Ihr müsst ihn nur aktivieren und dafür sorgen, dass er auf eurer Website ordnungsgemäß funktioniert.

User-Agent Stylesheets
Die User-Agent Stylesheets der Browser greifen auf die jeweiligen Standards zurück und eignen sich hervorragend, um einen nativen und auf Performance optimierten Dark Mode umzusetzen.

Color-scheme vs. prefers-color-scheme

Vergleichen wir nun beide Möglichkeiten miteinander, wird sofort klar, dass color-scheme es nicht erlaubt, eigene Werte festzulegen. Das geht nur mittels @media (prefers-color-scheme: dark). Der wiederum ist für kleine Websites schlichtweg ein Overkill. Hauptsächlich dann, wenn die ohnehin schon ein eher reduziertes Design verwenden.

Es ergibt in solchen Fällen nämlich einfach keinen Sinn, den Dark Mode mit @media (prefers-color-scheme: dark) zu realisieren. Das habe ich bei einigen meiner Designs zwar schon getan, doch sehe dafür mittlerweile absolut keine Notwendigkeit mehr. Auch deshalb, weil ich auf ein Brutalismus Design setzte und dementsprechend ohnehin auf die Standardwerte vertraue. Außerdem erspart mir der Befehl color-scheme einige Zeilen CSS-Code und ist am Ende schlichtweg performanter, da er auf native Werte zurückgreift, statt eigene zu setzen.

Das gilt im übrigen auch für die nativen Farben von CSS, weshalb ich hier auf der Website beispielsweise color: blue verwende und nicht color: #00f. Im Test wurden die nativen Farbnamen immer minimal schneller vom Browser gerendert als deren Kurzschreibweise (Shorthand) als Hexwert. Wobei ich ehrlicherweise sagen muss, dass es in der realen Umgebung einer Website keinen nennenswerten Unterschied ergibt und nur Performance-Fanatiker wie mich interessieren dürfte.

Das Problem bei dem Befehl color-scheme ist jedoch, dass der native Dark Mode nur dann funktioniert, wenn auch andere Standardwerte genutzt werden. Vergebe ich eine Farbe für den Body-Text, kann color-scheme schon nicht mehr korrekt angewandt werden. Nur wenn hier kein eigener Wert gesetzt ist, der Body also einfach den Standardwert color: black bekommt, funktioniert der native Dark Mode via color-scheme korrekt. Da gilt es gesondert drauf zu achten.

Dark Mode mit CSS umsetzen

Ein kleiner Trick wäre, dass ihr beide Angaben nutzt. Das kombiniert das Beste aus beiden Welten. Ihr verwendet also sowohl color-scheme als auch @media (prefers-color-scheme: dark). Auf diese Weise spart ihr euch immer noch einige CSS-Befehle, da ihr nur korrigieren müsst, was im nativen Dark Mode nicht möglich ist. Unter anderem die eben erwähnte Textfarbe, die ihr dann über den Befehl @media (prefers-color-scheme: dark) entsprechend anpassen könnt.

Alles andere wird aber weiterhin über color-scheme vom Browser gewählt. Nur die CSS-Befehle, die aufgrund eigener Anpassungen im Dark Mode nicht korrekt erscheinen, werden über @media (prefers-color-scheme: dark) hinzugefügt und entsprechend verändert. Durch die Kombination der beiden Befehle müsst ihr nur einzelne CSS-Klassen zum Dark Mode hinzufügen und leicht korrigieren. Alles andere wird weiterhin vom Browser als Dark Mode interpretiert und mittels color-scheme entsprechend aktiviert.

Persönlich setze ich hier auf der Website auf ein Brutalismus Design und dementsprechend eben rein auf die Standardwerte des jeweiligen Browsers. Bei mir reicht daher das einfache color-scheme: light dark aus. Doch was genau bedeutet das eigentlich? Schauen wir uns den Wert noch einmal etwas genauer an.

color-scheme CSS
Mit Color-scheme »light dark« wird der Light Mode priorisiert, der Dark Mode aber ebenfalls unterstützt. Alles nativ und ohne viel CSS-Code.

Color-scheme im Detail erklärt

Mit dem CSS Color Adjustment Module Level 1 wurden umfangreiche Möglichkeiten der automatischen Farbanpassung über den User-Agent eingeführt. Dabei geht es klar um den Dark Mode, ebenso wie um eine Kontrastanpassung oder unterschiedliche Farbschemata in den entsprechenden Browsern und Systemen.

Der Befehl color-scheme im CSS Color Adjustment Module Level 1 sorgt also dafür, dass das im System gewählte Farbschema auch im Browser bzw. auf der entsprechenden Website berücksichtigt wird. In diesem Fall kennt color-scheme drei verschiedene Werte, die diese Funktion dann noch genauer definieren können.

Die Werte werden dabei zusammen und mit der jeweiligen Präferenz angegeben. Also beispielsweise color-scheme:light dark, was angibt, dass der Light Mode Standard ist und bevorzugt, der Dark Mode aber ebenfalls unterstützt wird. Die Reihenfolge gibt somit an, welcher Modus für die Website vorgesehen ist und vom Betreiber entsprechend priorisiert wurde.

Color-scheme und prefers-color-scheme kombinieren

Nun gibt es auf vielen Seiten, die nicht absolut minimal gestaltet sind, größere Probleme mit dem color-scheme. Beispielsweise immer dann, wenn ein Hintergrund oder eine Schriftfarbe im :root gesetzt wurden. Denn dort, wo der Standard des Browsers überschrieben wird, greift auch color-scheme nicht mehr ein und kann den User-Agent Stylesheet dementsprechend nicht vollumfänglich anwenden.

Denn sobald eigene CSS-Befehle gesetzt sind, gilt der User-Agent Stylesheet nicht mehr. Dieser ist immer nur als eine Art Fallback zu verstehen, auf den zurückgegriffen wird, wenn kein individueller Wert gewählt wurde. Sobald jedoch ein eben solcher vorhanden ist, wird der User-Agent Stylesheet ignoriert. Und das führt bei color-scheme dann zwangsläufig dazu, dass der native Dark Mode in CSS nicht länger greift.

In diesem Fall müsst ihr color-scheme und @media (prefers-color-scheme: dark) in Kombination verwenden. Während color-scheme also alles in den Dark Mode versetzt, was nicht gesondert konfiguriert wurde, werden mit @media (prefers-color-scheme: dark) via CSS noch einmal die Klassen korrigiert, die bereits verändert wurden. Auf diese Weise spart ihr euch immer noch eine Menge CSS-Code. Jedenfalls dann, wenn es wirklich nur um die Schriftfarbe oder andere Farben geht, die geändert werden sollen.

Sobald ein Dark Mode zu komplex wird und der eigene Stylesheet nicht mehr auf native CSS-Standards zurückgreift, macht color-scheme oder die Kombination aus color-scheme und prefers-color-scheme jedoch keinen Sinn mehr. In diesem Fall bringt euch dann nur noch ein eigener Dark Mode via @media (prefers-color-scheme: dark) weiter. Für Website wie die meine jedoch ist color-scheme logischerweise die beste Wahl.

color-scheme prefers-color-scheme kombinieren
Um CSS-Code einzusparen, kann der native Dark Mode mit prefers-color-scheme kombiniert werden. Ihr passt dann nur die Stellen an, die vom nativen Dark Mode nicht korrekt dargestellt werden, da ihr sie mit eigenen Werten überschrieben habt.

Color-scheme als Meta-Tag verwenden

Ein kurzer Hinweis noch dazu, dass color-scheme auch via Meta-Tag eingesetzt werden kann. Das ist immer dann wichtig, wenn die CSS-Datei erst heruntergeladen werden muss. Ist das nämlich der Fall, wird der Befehl color-scheme erst interpretiert, wenn der CSS-Code vollständig im Browser vorliegt. Bei größeren Websites kann das ein wenig dauern, weshalb es dann zu Verzögerungen des Dark Modes kommt.

Da color-scheme jedoch auf Standards setzt und nur dann perfekt funktioniert, wenn der CSS-Code entsprechend minimal gehalten wird, ist dieser meist ohnehin als Inline-Style integriert. Daher wird es hier auch keine Verzögerungen geben. Genau wie es bei mir auf der Website keine Verzögerung gibt. Wer trotzdem den Meta-Tag statt color-scheme verwenden möchte, kann den Dark Mode mit dieser Vorlage hinzufügen.

<meta name="color-scheme" content="light dark">

Im Beispiel ist der Light Mode Standard, es kann aber auch der Dark Mode genutzt werden, wenn die Nutzer*innen diesen bei sich ausgewählt haben und dementsprechend bevorzugen. Persönlich würde ich immer die CSS-Variante wählen, bevor ich einen weiteren Meta-Tag in den Head integriere.

Bilder im Dark Mode verändern

Ein Problem, welches im Dark Mode häufig in Erscheinung tritt, sind besonders grelle Farben. Gerade Bilder strahlen dann regelrecht und das ist nicht nur unangenehm für das Auge, sondern es passt auch nicht zur ansonsten eher dunklen Darstellung der Website. Eine clevere Möglichkeit kann es daher sein, mittels @media (prefers-color-scheme: dark) für ein wenig Abdunkelung bei den Bildern zu sorgen.

Dafür bieten sich die CSS-Filter an, mit denen ihr die Helligkeit ganz einfach verringern und den Kontrast erhöhen könnt. Ersteres verhindert den strahlenden Effekt im Dark Mode und zweiteres sorgt dafür, dass die Bilder dennoch nicht ihre Tiefe und Kraft verlieren. Hier eine Empfehlung meinerseits, was die jeweiligen Werte angeht.

@media (prefers-color-scheme: dark){ img{filter: brightness(0.85) contrast(1.1);}}

Mittlerweile ist es auch möglich, die eingebundenen Bilder an den Dark Mode anzupassen. Das ergibt für Blogs oder Artikel vermutlich eher weniger Sinn, kann aber auf Landing Pages dafür sorgen, dass jedes Element besonders stimmig erscheint. Im Dark Mode könnten dann dunkle Versionen der Bilder, Icons und Infografiken angezeigt werden. Das geht via Picture-Tag sogar direkt in HTML.

<picture><source srcset="dark-mode.jpg" media="(prefers-color-scheme: dark)"><img src="light-mode.jpg"></picture>

Somit wird das dark-mode.jpg geladen, wenn der Dark Mode im Browser entsprechend aktiv ist. Wenn nicht, fällt der Ladevorgang auf den Fallback, also das light-mode.jpg zurück. Eine einfache Lösung, die allerdings von euch verlangt, dass ihr zwei unterschiedliche Versionen von allen verwendeten Bildern erstellt.

Helle Bilder Dark Mode
Im Dark Mode kann es passieren, dass helle Bilder unangenehm leuchten. Mittels CSS-Filter kann die Helligkeit korrigiert werden. Die Bilder erscheinen dann ein wenig abgedunkelt.

Favicon im Dark Mode anpassen

Was für Bilder möglich ist, kann auch bei dem verwendeten Favicon eingesetzt werden. Jedenfalls dann, wenn ihr euer Favicon als modernes SVG vorliegen habt. Das SVG-Favicon wird von Browsern inzwischen breitflächig unterstützt, ihr solltet aber dennoch stets ein klassisches favicon.ico als Fallback im Hauptverzeichnis liegen haben.

Damit sich das Favicon im Dark Mode entsprechend anpassen lässt, müsst ihr innerhalb der SVG-Datei einen Style-Tag hinzufügen und alle Elemente innerhalb der SVG via CSS gestalten, also mit Klassen oder IDs versehen. Nur auf diese Weise ist es möglich, innerhalb des Styles ein @media (prefers-color-scheme: dark) hinzuzufügen.

Hier könnt ihr dann alle Elemente innerhalb des SVG-Favicons verändern und im Dark Mode entsprechende Unterschiede herausarbeiten. Je nachdem wie komplex euer SVG-Favicon ist, erfordert das allerdings ein wenig Handarbeit. Es lohnt sich jedoch, da ein angepasstes Favicon einen guten Eindruck hinterlässt und im Browser meist auch gesondert auffällt.

Modi für verschiedene Systemeinstellungen

Es gibt neben dem nativen Dark Mode via color-scheme und dem angepassten Dark Mode über @media (prefers-color-scheme: dark) noch weitere Möglichkeiten zur Anpassung via CSS. Diese können, je nach Website auch eine wichtige Rolle spielen.

So sorgt @media (-ms-high-contrast: active) beispielsweise für besondere Anpassungen im High-Kontrast-Modus unter Windows. Auch @media (prefers-reduced-motion) kann verwendet werden, um etwaige Animationen zu deaktivieren, wenn unter MacOS die Option »reduzierte Bewegung« aktiviert wurde.

Persönlich gehe ich davon aus, dass solche individuellen Anpassungen in Zukunft eine immer größere Rolle spielen werden. Einfach deshalb, weil Barrierefreiheit wichtiger geworden ist und auf diese Weise mit relativ wenig Aufwand dafür gesorgt werden kann, dass systemweite Optionen auch auf Websites berücksichtigt werden. Genau wie das Gendern alltäglich geworden ist, wird auch die Barrierefreiheit daher etwas ganz Normales werden.

Gründe für einen Dark Mode

Zum Schluss noch einmal ein paar gute Gründe dafür, warum auch ihr einen Dark Mode für eure Website umsetzten solltet. Einer der Hauptgründe ist die eben erwähnte Barrierefreiheit. Wenn Nutzer*innen etwas an den Augen haben oder helle bzw. dunkle Farben schlechter sehen können, benötigen sie derartige Modi, um eure Website bedienen zu können. Rücksicht darauf zu nehmen ist dank nativem Dark Mode einfacher als jemals zuvor.

Auf OLED-Displays verbrauchen dunkle Farben zudem weniger Energie. Wer auf seinem iPhone einen schwarzen Hintergrund gewählt hat, wird das bereits wissen. Es sind nur einige Prozent, doch wer sein Smartphone über den Tag hinweg viel im Einsatz hat, wird den Unterschied meist dennoch recht deutlich merken. Hier empfehle ich euch gerne meine Dockless/Notchless Wallpaper, mit denen ich selbst nur gute Erfahrungen bezüglich Akkuverbrauch sammeln konnte. Der geringere Energiebedarf ist natürlich auch nachhaltiger und somit wiederum gut für die Umwelt.

In meinen Augen ist der Dark Mode auch im Hinblick auf die Suchmaschinenoptimierung relevant. Weil er für Nutzer*innen gemacht wurde und die Zufriedenheit der Nutzer*innen der SEO-Faktor schlechthin geworden ist. Persönlich halte ich einen Dark Mode, wie auch immer er aussieht, daher für absolut notwendig, auch in Bezug auf SEO.

Allerdings ist der Dark Mode heutzutage sowieso Pflicht. Jedes System hat inzwischen eine entsprechende Einstellung für Dark Mode oder Light Mode und genau diese Einstellungen werden mittels CSS problemlos auch auf Websites berücksichtigt. Das geht sogar mit einem nativen Dark Mode, wie ich ihn hier vorgestellt habe. Es gibt somit keinen Grund mehr, warum jemand keinen Dark Mode auf seiner Website anbieten sollte.

Energiespar Wallpaper
Ein dunkles Wallpaper spart bei einem OLED-Display viel Energie. Hier im Bild eines meiner Dockless/Notchless Wallpaper, welches Dock und Notch bestmöglich versteckt.

Meinung zum nativen Dark Mode

Am Ende ist der native Dark Mode mit CSS oder besser gesagt dem User-Agent Stylesheet des jeweiligen Browsers eine gute Wahl, um CSS-Code einzusparen. Gleichzeitig mag ich es, auf Standards zurückzugreifen, die dann entsprechend automatisch korrekt interpretiert werden. Viele Websites sind überdesignt, ohne dass dies in irgendeiner Weise Sinn ergeben würde. Weil es möglich ist, wird alles animiert, besonders aufwendig dargestellt und am Ende kommt ein Design dabei heraus, welches nicht mehr den Nutzer*innen dient, sondern nur die Verspieltheit der Designer*innen präsentiert.

In meiner gesamten Laufbahn als Content Manager und SEO waren es stets die einfachsten Websites, die am besten funktioniert haben. Also die, die im Volksmund gerne mal als »hässlich« bezeichnet wurden. Doch je einfacher die Darstellung und je standardisierter die Werte, desto besser kann eine Website schlussendlich verwendet werden. Und sind Websites am Ende nicht für Menschen gemacht, die mehr Wert auf die Funktion als die Form legen?

Das fängt schon bei den Links an, die klassischerweise immer blau und unterstrichen waren und auch heute noch in Blau bestmöglich als solche erkannt werden. Außerdem bedeutet ein standardisiertes Design immer auch, dass die Performance stimmt. Brutalismus Design mag roh und rau erscheinen, entpuppt sich am Ende aber oft als besonders durchdacht und bewusst simpel. Für mich ergibt das Sinn. Einfach deshalb, weil es am besten funktioniert.

Das gilt auch für den nativen Dark Mode. Es besteht kein Anlass dazu, einen Dark Mode aufwendig selbst zu gestalten. Weniger Eitelkeit, mehr Performance ist für mich das Motto von modernen und barrierefreien Webdesign.