Second approach to implement 'prefers-color-scheme'
While writing my post Hexo and the Dark Mode a few days ago, I thought it would be nice, if I could switch between the normal (light) and the dark theme, I’ve created for the support of the OS-related Dark Mode, even manually. The only thing I needed was a toggle element and a little bit of JavaScript.
Of course, I couldn’t manipulate the media query prefers-color-scheme itself, but introduce a different way by blog uses it. Instead of implementing the media query directly into my CSS (or Stylus) code, I used a root selector, which can be manipulated by JavaScript … something like this:
Some explanations on the Stylus syntax: / means the root of the DOM and & points to the parent selector. Therefore the example will be rendered into this:
Only problem was: the “Root + Parent” Stylus selector doesn’t work in the block variables in the _extend.styl. So I had to copy all theme relevant styles directly to the elements, where such a block was used: @extend <block-name>.
The Toggle Switch
In the footer.ejs I added a toggle checkbox, where I could bind my JavaScript…
The icon variables are defined in the _variables.styl like this:
1 2
icon-moon = "\f186" icon-sun = "\f185"
The JavaScript
Everything was now prepared to implement the switching code in JavaScript, which should support a manual switch by clicking the toggle element as well as the automatic switch by the OS.
I wrapped all necessary code into a seperate JS file and placed a reference in the after-footer.ejs, which places it at the bottom of the HTML:
functiondetectColorScheme() { var theme = "light"; //default
// get last used theme from local cache if(localStorage.getItem("theme")){ if(localStorage.getItem("theme") === "dark"){ theme = "dark"; } } elseif(!window.matchMedia) { // matchMedia not supported returnfalse; } elseif(window.matchMedia("(prefers-color-scheme: dark)").matches) { // OS has set Dark Mode theme = "dark"; }
// set detected theme if (theme === "dark") { setThemeDark(); } else { setThemeLight(); } }
// Listener for theme change by toggle toggleTheme.addEventListener('change', function(e) { if (e.target.checked) { setThemeDark(); } else { setThemeLight(); } }, false);
// Listener for theme change by OS var toggleOS = window.matchMedia('(prefers-color-scheme: dark)'); toggleOS.addEventListener('change', function (e) { if (e.matches) { setThemeDark(); } else { setThemeLight(); } });
// call theme detection detectColorScheme();
By using the both addEventListener‘s, each switch will be recognized and this approach is capable to support even more themes, just by using different values in the data-theme attribute.
Webmentions
No Webmentions yet...
In case your blog software can't send Webmentions,
you can use this form to submit me a mention of this article...
Comments