Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override css prefers-color-scheme setting

I am implementing a dark mode, as macOS, Windows and iOS have all introduced dark modes.

There is a native option for Safari, Chrome, and Firefox, using the following CSS media rule:

@media (prefers-color-scheme: dark) { body {     color:#fff;     background:#333333 } 

This will automatically identify systems that are set to dark modes, and apply the enclosed CSS rules.

However; even though users may have their system set to dark mode, it may be the case that they prefer the light or default theme of a specific website. There is also the case of Microsoft Edge users which does not (yet) support @media (prefers-color-scheme. For the best user experience, I want to ensure that these users can toggle between dark and default modes for those cases.

Is there a method that this can be performed, possibly with HTML 5 or JavaScript? I'd include the code I have tried, but I haven't been able to find any information on implementing this whatsoever!

like image 798
JimmyBanks Avatar asked May 24 '19 22:05

JimmyBanks


People also ask

How do I stop Dark mode from destroying my CSS?

Go to Chrome and type address chrome://flags then search for "dark" You'll find "Force Dark Mode for Web Contents" flag. If it's not already - set if to "default". Hope it saves some time anybody, I've wasted 1h over this.

Can I use prefer color scheme?

At the time of writing, prefers-color-scheme is supported on both desktop and mobile (where available) by Chrome and Edge as of version 76, Firefox as of version 67, and Safari as of version 12.1 on macOS and as of version 13 on iOS. For all other browsers, you can check the Can I use support tables.

What is color scheme CSS?

The color-scheme CSS property allows an element to indicate which color schemes it can comfortably be rendered in. Common choices for operating system color schemes are "light" and "dark", or "day mode" and "night mode".


2 Answers

I have determined an appropriate solution, it is as follows:

CSS will use variables and themes:

// root/default variables :root {     --font-color: #000;     --link-color:#1C75B9;     --link-white-color:#fff;     --bg-color: rgb(243,243,243); } //dark theme [data-theme="dark"] {     --font-color: #c1bfbd;     --link-color:#0a86da;     --link-white-color:#c1bfbd;     --bg-color: #333; } 

The variables are then called where necessary, for example:

//the redundancy is for backwards compatibility with browsers that do not support CSS variables. body {     color:#000;     color:var(--font-color);     background:rgb(243,243,243);     background:var(--bg-color); } 

JavaScript is used to identify which theme the user has set, or if they have over-ridden their OS theme, as well as to toggle between the two, this is included in the header prior to the output of the html <body>...</body>:

//determines if the user has a set theme function detectColorScheme(){     var theme="light";    //default to light      //local storage is used to override OS theme settings     if(localStorage.getItem("theme")){         if(localStorage.getItem("theme") == "dark"){             var theme = "dark";         }     } else if(!window.matchMedia) {         //matchMedia method not supported         return false;     } else if(window.matchMedia("(prefers-color-scheme: dark)").matches) {         //OS theme setting detected as dark         var theme = "dark";     }      //dark theme preferred, set document with a `data-theme` attribute     if (theme=="dark") {          document.documentElement.setAttribute("data-theme", "dark");     } } detectColorScheme(); 

This javascript is used to toggle between the settings, it does not need to be included in the header of the page, but can be included wherever

//identify the toggle switch HTML element const toggleSwitch = document.querySelector('#theme-switch input[type="checkbox"]');  //function that changes the theme, and sets a localStorage variable to track the theme between page loads function switchTheme(e) {     if (e.target.checked) {         localStorage.setItem('theme', 'dark');         document.documentElement.setAttribute('data-theme', 'dark');         toggleSwitch.checked = true;     } else {         localStorage.setItem('theme', 'light');         document.documentElement.setAttribute('data-theme', 'light');         toggleSwitch.checked = false;     }     }  //listener for changing themes toggleSwitch.addEventListener('change', switchTheme, false);  //pre-check the dark-theme checkbox if dark-theme is set if (document.documentElement.getAttribute("data-theme") == "dark"){     toggleSwitch.checked = true; } 

finally, the HTML checkbox to toggle between themes:

<label id="theme-switch" class="theme-switch" for="checkbox_theme">     <input type="checkbox" id="checkbox_theme"> </label> 

Through the use of CSS variables and JavaScript, we can automatically determine the users theme, apply it, and allow the user to over-ride it as well. [As of the current time of writing this (2019/06/10), only Firefox and Safari support the automatic theme detection]

like image 195
JimmyBanks Avatar answered Sep 19 '22 11:09

JimmyBanks


You can use my custom element <dark-mode-toggle> that initially adheres to the user's prefers-color-scheme setting, but that also allows the user to (permanently or temporarily) override it. The toggle works both with separate CSS files or with classes that are toggled. The README has examples for both approaches.

like image 42
DenverCoder9 Avatar answered Sep 22 '22 11:09

DenverCoder9