Met een schakelaar voor de donkere modus kunnen gebruikers het kleurenschema van het systeem voor één site overschrijven.
De overschrijving wordt toegepast door <meta name="color-scheme"> te updaten: light dark betekent 'volg de systeemvoorkeur', light of dark zet een expliciet schema vast.
Kleuren (light-dark()), systeemkleuren en de systeemeigen UI zijn allemaal afhankelijk van de CSS-property color-scheme. De schakelaar werkt dus door die property te synchroniseren met de <meta> (zie De overschrijving weerspiegelen in CSS).
Een permanente schakelaar, instellingenbeheer of helemaal geen schakelaar?
De meeste sites hebben geen permanente schakelaar voor het kleurenschema nodig in de UI van de site (koptekst, navigatie, voettekst, enzovoort). Volg standaard de systeemvoorkeur en plaats de bedieningselementen op een afzonderlijke instellingenpagina, -deelvenster of -overlay als een handmatige overschrijving nodig is.
Een schema vastzetten tegen het OS is een legitieme maar zeldzame intentie, en zeldzame intenties horen achter progressieve openbaarmaking, niet in een bedieningselement dat altijd zichtbaar is.
Permanente schakelaars vind je meestal op sites voor ontwikkelaars of sites die aan ontwikkelaars gerelateerd zijn (bijvoorbeeld voor ontwerpers), waar het wisselen van schema's veel vaker voorkomt dan voor de gemiddelde webgebruiker. Voeg er NIET een toe alleen omdat dit een veelvoorkomend patroon is op ontwikkelaarssites: de interesse van de ontwikkelaar in deze bedieningselementen is niet representatief voor gewone gebruikers.
Implementatie
Volg eerst alle stappen in Donkere modus om beide schema's te ondersteunen, waarbij de systeemvoorkeur standaard is.
Gegevensmodel
Het gegevensmodel voor de schakelaar voor de donkere modus bevat meestal 3 statussen:
- Systeem (geen opgeslagen waarde): De UI volgt het kleurenschema van het systeem. Dit is idealiter de standaardinstelling.
- Licht (opgeslagen als
"light"): De UI gebruikt het lichte thema, ongeacht het kleurenschema van het systeem. - Donker (opgeslagen als
"dark"): De UI gebruikt het donkere thema, ongeacht het kleurenschema van het systeem.
Deze status wordt meestal opgeslagen in localStorage en weerspiegeld in een <meta name="color-scheme">-element in de documentkop.
De overschrijving weerspiegelen in CSS
De <meta> is alleen een presentatiehint: elke color-scheme-declaratie in de CSS van de auteur overschrijft deze.
Omdat de Donkere modus color-scheme: light dark instelt op :root, is alleen de <meta> updaten een no-op: CSS wint.
Wijs de <meta> weer toe aan de property, zodat de cascade deze volgt:
:root {
color-scheme: light dark;
&:has(> head > meta[name="color-scheme"][content="dark"]) {
color-scheme: dark;
}
&:has(> head > meta[name="color-scheme"][content="light"]) {
color-scheme: light;
}
}
Gebruik GEEN hardcoded color-scheme: light of color-scheme: dark als de standaard root. De basisdeclaratie MOET light dark blijven.
CSS mag NIET afhankelijk zijn van JS: als JS nooit wordt uitgevoerd, blijft de <meta> light dark en volgt de site de systeemvoorkeur. Er gaat niets mis.
Persistentie en FOUC-preventie
Behoud de overschrijving in localStorage. Verwijder de invoer als je teruggaat naar de systeemstandaard.
Als je wilt voorkomen dat het verkeerde schema even wordt getoond, pas je de opgeslagen waarde toe in een inline script (NIET type=module, NIET defer) dat direct na het element <meta> wordt geplaatst:
<meta name="color-scheme" content="light dark">
<script>
document.querySelector('meta[name="color-scheme"]').content = localStorage.getItem("color-scheme") ?? "light dark";
</script>
- Dit inline script bestaat alleen om FOUC te voorkomen. Houd het zo klein mogelijk. Extra JS voor het schakelen tussen kleurenschema's kan later worden geladen.
- In zeldzame gevallen kan
localStorage-toegang een fout veroorzaken (bijvoorbeeld als sitegegevens worden geblokkeerd), maar omdat dit script niets anders doet, is het enige neveneffect een consolefout. Wrap intry .. catchif this matters. Zorg dat het thema nog steeds op de pagina is toegepast, zelfs als het niet kan worden opgeslagen. - De overschrijving kan worden gewijzigd via een ander tabblad: verwerk de gebeurtenis
storagevanwindowom gesynchroniseerd te blijven. - Gebruik
matchMedia()NIET om de opgeslagen waarde te verwijderen als de systeemvoorkeur verandert om overeen te komen. Het OS van veel gebruikers wisselt automatisch van schema op basis van het tijdstip. Als de opgeslagen waarde wordt verwijderd wanneer de 2 samenvallen, is het onmogelijk om een schema vast te zetten.
Vertakking voor HTML- en niet-kleurwaarden
Voor kleuren hoef je niets extra's te doen: nadat de <meta> is toegewezen aan color-scheme (hierboven), volgt light-dark() de overschrijving.
Dit gedeelte gaat over het aanpassen van andere waarden (bijv. font-weight, mediabronnen, enzovoort).
Als de pagina de systeemvoorkeur volgt, kan (prefers-color-scheme: dark) worden gebruikt voor vertakking, waaronder in <picture>- of <video>-bronnen.
Het overschrijven van het kleurenschema voegt een extra complicatie toe: de systeemvoorkeur is niet langer de bron van waarheid en voor API's die alleen mediaquery's accepteren, is er geen direct alternatief.
Vertrouw NIET uitsluitend op door JS toegepaste klassen zoals .dark voor vertakking, omdat deze onjuist zijn als JS niet wordt geladen en de standaardinstelling van het OS donker is.
U kunt de mediaquery combineren met een :root:has(> head > meta[name="color-scheme"][content="dark"])- (of light-)kiezer om te vertakken.
Ga naar Combinaties van selectors en @-regels voor meer informatie over hoe u dit op een elegante manier implementeert.
De eigen opties van het bedieningselement zijn ook niet-kleurvertakkingen: neem beide statussen op in de opmaak (icoon plus visueel verborgen actietekst, bijvoorbeeld 'Overschakelen naar donker thema') en verberg de inactieve status via deze kiezers.
display: none verwijdert ook de overbodige optie uit de AT, zodat de bediening geen JS nodig heeft om up-to-date te blijven als de systeemvoorkeur verandert.
Voor in-HTML-media is de enige manier op dit moment om beide versies als afzonderlijke elementen op te nemen en de zichtbaarheid op de juiste manier in te stellen.
Het verbergen van <source>-elementen met display: none werkt niet.
Gebruikersinterface
2 of 3 staten?
In alle gevallen MOET de UI ondersteuning bieden voor het terugzetten of instellen van het kleurenschema op systeem.
Geef de voorkeur aan 2 statussen in schakelaars met beperkte ruimte, zoals permanente schakelaars in de site-chrome (koptekst, navigatie, voettekst, enzovoort) waar de ruimte beperkt is en het aanpassen van instellingen meestal loodrecht op het gebruikersdoel staat.
Een kleurenschemabediening in een afzonderlijk instellingengebied (pagina, deelvenster of overlay) is een ander scenario en KAN alle 3 de statussen expliciet tonen (Licht, Donker, Systeem): daar neemt de gebruiker al bewuste beslissingen over toekomstig gedrag en is er ruimte om de opties uit te leggen.
3 expliciete statussen zijn ook gerechtvaardigd als de site contextbewuste schema's implementeert (bijvoorbeeld een gedimde lichte modus als het OS donker is), omdat Licht en Systeem (momenteel licht) dan echt verschillen.
Schakelaars met 2 statussen
Als zo'n bedieningselement wordt gebruikt, is dat meestal een tijdelijke aanpassing van het comfort ('het is nu te licht') in plaats van dat de huidige status op de lange termijn wordt behouden. Voor schakelaars met 2 statussen is het daarom voldoende om 2 van de 3 instellingen te tonen: systeem (zodat de instelling kan worden teruggezet) en het huidige tegenovergestelde van systeem, opgeslagen als de huidige letterlijke waarde.
De enige 2 staten moeten zijn:
- Systeemstandaard: geen opgeslagen waarde,
<meta>contentlight dark. Wordt getoond als de huidige opgeloste waarde (bijvoorbeeld een zon-icoon als het licht is). - Overschrijven: Wordt letterlijk opgeslagen als
lightofdark.
In wezen is het een bedieningselement met 3 statussen (light dark, light, dark) waarbij de expliciete status die overeenkomt met de huidige systeemvoorkeur onbereikbaar is.
Als de gebruiker de schakelaar omzet:
- Doelschema = het tegenovergestelde van het momenteel weergegeven schema (opgeslagen waarde indien aanwezig, anders systeemvoorkeur). De gebruiksintentie is 'selecteer het tegenovergestelde van wat ik nu zie', NIET 'selecteer het omgekeerde van de systeemstandaard'.
- Als het doel verschilt van de huidige systeemvoorkeur, sla je het letterlijk op.
- Als het doel overeenkomt met de huidige systeemvoorkeur, maakt de gebruiker de aanpassing ongedaan: verwijder de opgeslagen waarde. Sla het NIET op. Anders wordt het schema onzichtbaar vastgezet tegen toekomstige systeemwijzigingen.
- Stel de content van
<meta>in op de opgeslagen waarde of oplight darkals er geen waarde is.
BELANGRIJK: Afwijking mag alleen worden gecontroleerd op het moment van opslag, nooit met terugwerkende kracht: een opgeslagen waarde die de systeemvoorkeur later wijzigt om overeen te komen, MOET worden bewaard. Het OS van veel gebruikers wisselt automatisch van schema op basis van het tijdstip. Als de opgeslagen waarde wordt verwijderd wanneer de 2 samenvallen, is het onmogelijk om een schema vast te zetten.
Voorbeeldscenario, beginnend met het OS ingesteld op licht:
- De gebruiker zet de schakelaar aan. Donker verschilt van de systeemvoorkeur, dus
darkwordt opgeslagen. De site wordt donker. - De OS-instelling verandert in donker. De site blijft donker (de opgeslagen waarde komt nu overeen met de systeemvoorkeur, maar wordt bewaard).
- De OS-instelling verandert weer in licht. De site blijft donker.
- De gebruiker zet de schakelaar aan. Het doel (licht) komt overeen met de systeemvoorkeur, dus de opgeslagen waarde wordt verwijderd en de site volgt het systeem weer.
Schakelaars met 3 statussen
Als er meer ruimte is en gebruikers al in de mindset zijn om voorkeuren voor de lange termijn in te stellen, kan een bedieningselement met 3 statussen meer duidelijkheid bieden. In dit geval wordt het gegevensmodel netjes toegewezen aan de 3 UI-opties: systeem, licht en donker.
De optie Systeem moet ook de huidige systeeminstelling tonen om de cognitieve belasting te verminderen, bijvoorbeeld via:
- Icoon, bijvoorbeeld een zon-icoon rechtsonder het systeemicoon
- Tekst, bijvoorbeeld 'Systeem (momenteel licht)'