Es gibt viel zu bedenken, wenn man ein Dunkelmodus-Theme für eine Website implementiert. Wir haben einen umfangreichen Leitfaden dazu. Es gibt einige sehr clevere schnelle Lösungen, aber es gibt auch einige ziemlich knifflige Dinge zu meistern. Eines dieser kniffligen Dinge ist, dass es sich nicht um einen Dunkelmodus-"Schalter" zwischen dunkel und hell handelt, sondern eigentlich um drei Modi, die Sie unterstützen müssen: dunkel, hell und Systempräferenz verwenden. Dies ähnelt der Funktionsweise von Audioeinstellungen in vielen Anwendungen, die es Ihnen ermöglichen, sehr spezifisch auszuwählen, welchen Audioeingang oder -ausgang Sie verwenden möchten, oder die Systempräferenz zu verwenden.
CSS und JavaScript können den Systempräferenz-Aspekt über die prefers-color-scheme API handhaben, aber wenn die Benutzereinstellung geändert wurde und diese Einstellung nun von der Benutzereinstellung abweicht, befinden Sie sich im Bereich des "Flash of inAccurate coloR Theme" oder FART. Okay, okay, es ist ein Augenzwinkern-Akronym, aber es ist ein potenziell ziemlich visuell störendes Problem, also behalte ich es bei. Es ist im gleichen Sinne, wie FOUT (Flash of Unstyled Text) für das Laden von Schriftarten ist.
Das Speichern einer Benutzereinstellung bedeutet etwas wie einen Cookie, localStorage oder eine Art Datenbank. Wenn der Zugriff auf diese Daten die Ausführung von JavaScript erfordert, z. B. localStorage.getItem('color-mode-preference');, dann befinden Sie sich im FART-Bereich, da Ihr JavaScript sehr wahrscheinlich nach dem ersten Rendern einer Seite ausgeführt wird, es sei denn, Sie verzögern unnötigerweise das Rendern der Seite.
Sie können mit einer serverseitigen Sprache auf einen Cookie zugreifen, bevor die Seite gerendert wird, was bedeutet, dass Sie ihn verwenden könnten, um etwas wie <html class="user-setting-dark-mode"> auszugeben und entsprechend zu stylen, was FART geschickt vermeidet, aber das bedeutet eine Website, die überhaupt Zugriff auf eine serverseitige Sprache hat (Jamstack-Websites zum Beispiel nicht).
All das, um zu sagen, dass ich den Artikel von Rob Morieson über Dark Mode geschätzt habe, weil er dieses wichtige Problem nicht scheute. Es geht sehr spezifisch um die Umsetzung in Next.js und verwendet localStorage, aber da Next.js JavaScript-gerendert ist, können Sie es zwingen, die gespeicherte Benutzereinstellung als allererstes zu überprüfen. Das bedeutet, dass es beim ersten Mal korrekt gerendert wird (kein Flash). Sie müssen jedoch das serverseitige Rendering deaktivieren, damit dies funktioniert, was jedoch ein unschöner Kompromiss ist.
Ich bin nicht davon überzeugt, dass es einen guten Weg gibt, FART ohne serverseitige Sprache oder verzögerte Seiten-Renderings zu vermeiden.
Wie schlimm ist das, dass es nicht einmal erwähnt wird?
const theme = localStorage.getItem(‘color-mode-preference’) || ‘system’
document.body.classList.add(`theme-setting-${theme}-mode`)
Das ist der springende Punkt. Dieses JavaScript wird höchstwahrscheinlich ausgeführt, nachdem die Seite gerendert wurde.
Ou. Ich habe vergessen zu erwähnen, dass man das direkt nach dem öffnenden Tag einfügen muss. Entschuldigen Sie bitte.
const theme = localStorage.getItem(‘color-mode-preference’) || ‘system’
document.body.classList.add(`theme-setting-${theme}-mode`)
Jetzt sehe ich, dass auch andere das vorschlagen.
Dieses Akronym. Großartig.
Ein trickreicher Weg, dies zu umgehen, könnte die Verwendung eines Service Workers und der Caching-API sein, um die auf Anfrage abgerufene CSS-Datei zu aktualisieren. Das wäre etwas ziemlich Interessantes.
Dies könnte tatsächlich ein guter Anwendungsfall für einen Service Worker sein, besonders wenn Sie ihn bereits verwenden. Wenn jemand explizit eine Präferenz für einen dunklen oder hellen Modus gewählt hat, können Sie seine Netzwerkanfrage für das Haupt-Stylesheet (das die `prefers-color-scheme`-Medienabfragen enthält) abfangen und es durch eine gecachte Version des Stylesheets überschreiben, das nur die Stile für das angegebene Farbschema enthält.
Ich bin mir nicht sicher, ob ich den Teil mit localStorage verstehe. Next.js ist React auf der Serverseite (Node.js), daher sollten Sie Cookies verwenden und nicht localStorage, da dies nur auf der Client-Seite verfügbar ist.
Hier ist eine grundlegende Implementierung davon in Nuxt.js. Das Äquivalent zu Next.js, aber für Vue. Die Verwendung eines Cookies und die Ausführung auf der Serverseite ist tatsächlich viel besser, da sie das Rendern der Seite nicht verzögert, bis das JS geparst und ausgeführt wird.
Sie könnten ein kleines Skript wie dieses in den Head der Seite einfügen und ich glaube nicht, dass die Verzögerung zu groß ist.
Websites wie https://mxb.dev/ oder meine verwenden diese Technik bereits.
Wie wäre es damit, die Seite komplett auszublenden, bevor die Benutzereinstellung für das Theme bekannt ist? Verwenden Sie einen mittleren Grauton als Übergang und blenden Sie dann zum hellen oder dunklen Theme über, wenn möglich...
Das meine ich mit erzwungener Verzögerung. Fühlt sich wie ein hoher Preis für das an.
Außerdem ist 'no-js-no-content' eine der schlimmsten Entwicklungen im Web der letzten Jahre.
Wenn Sie die Seite ausblenden müssen, verwenden Sie etwas wie
body.preloaderim Markup; und im CSSJa. Ich würde gerne sehen, dass dieses Problem weniger vernachlässigt wird. Ich würde mich sogar mit dem Standardmäßig dunklen Körperhintergrund zufriedengeben, da bei FART die Leute, die helle Farben bevorzugen, nicht so stark beeinträchtigt werden wie umgekehrt.
https://twitter.com/hotplinth/status/1382844581486682118
Ein kleines Inline-JavaScript im HTML-Header, das die Benutzereinstellung aus einem Cookie oder localStorage lädt, scheint meiner Meinung nach keine allzu große Verzögerung beim Rendern zu verursachen.
Ja, da stimme ich zu. Ich habe auch gesehen, dass ein kleines Skript-Tag als erstes Element innerhalb des Body-Tags platziert wird, wo Theme-Einstellungen überprüft und umgesetzt werden. Ich würde nicht sagen, dass dies das Rendern spürbar beeinträchtigt ... zumindest im Vergleich zu allem anderen, was wir täglich tun.
Stellen Sie einfach sicher, dass Sie die Dunkelmodus-CSS-Klasse vor allen
<link rel="stylesheet">- und<style>-Tags platzieren.Ich bin nicht davon überzeugt, dass Blitze von ungenauen Farbthemen das große Problem sind. Soweit ich sehen kann
ein Blitz von Weiß, der vor dem Laden eines dunklen Themas auftritt, ist in einem dunklen Raum bei ausgeschaltetem Licht fantastisch unangenehm.
Ein Blitz von schwarzem Bildschirm, der draußen bei Tageslicht betrachtet wird, sieht lediglich aus, als wäre ein Teil des Bildschirms für den Bruchteil einer Sekunde ausgeschaltet.
In Anbetracht dieser Asymmetrie wäre es nicht besser, dieses Problem als "Blitze von Weiß sind um jeden Preis zu vermeiden; Blitze von Schwarz sind viel, viel weniger schlimm" zu betrachten und mit dem Schreiben von Stylesheets zu beginnen, die primär für den Dunkelmodus sind?
Ich habe noch nicht an Websites gearbeitet, bei denen FOUT etwas ist, das ich beheben musste, aber wie wäre es mit etwas wie diesem
Auf diese Weise erhalten Seiten ein Farbschema von Schwarz auf Weiß, bevor der Browser überhaupt anfängt zu rendern, und niemand wird im Bett geblendet.
Hallo, ich habe versucht, eine Lösung für dieses Problem zu finden.
https://medium.com/@lyxsus/fixing-fart-flash-of-inaccurate-color-theme-for-static-websites-7935f7f85e20
Das habe ich eine Weile so gemacht, indem ich ein Skript-Tag am Anfang des Dokuments platziert habe. Es half, den Flash ohne spürbare Leistungseinbußen zu umgehen. Ich habe darüber geschrieben:
https://blog.jim-nielsen.com/2018/icon-galleries-dark-mode/
Zugegebenermaßen erfordert es JavaScript. Schließlich habe ich diese Funktionalität entfernt, indem ich den UI-Schalter für den dunklen Modus entfernt und mich ausschließlich auf `prefers-color-scheme` verlassen habe, was die Notwendigkeit von serverseitigem Rendering oder JS-Tricks zur Beibehaltung des Zustands eines dunklen oder hellen Modus-Schalters umgeht.
Es gibt jetzt einen neuen Vorschlag, um FART zu verhindern: https://github.com/WICG/user-preference-media-features-headers
Dies würde es ermöglichen, Benutzereinstellungen (wie z. B. das bevorzugte Farbschema) im Header der anfänglichen Anfrage zu hinterlegen.