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!
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.
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.
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".
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]
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With