Respecting User Dark Mode
I am pretty particular about my light and dark settings being respected. After all, there’s nothing worse than pulling a website up in a dark room and all you’re eyeballs are presented with is a blindingly bright white screen.
MacOS (and I assume Windows) introduced user preferences around this a few major releases ago and it’s also supported in major browsers.
Then a few months ago I saw Scott Hanelsman tweet about respecting the user’s preference on websites and it got me thinking that I should update this site.
How to detect if the User's OS prefers *dark mode* and change your site with CSS and JS! https://t.co/Y231y4TYf3 https://t.co/Z6WNKYzsnV
— Scott Hanselman 🌮 (@shanselman) September 21, 2021
Overall, I’ve really enjoyed the simplicity of the “Hello Friend” theme. After seeing the above though, I wasn’t such a fan of forcing viewers into “dark” mode, which is what I have this blog defaulted to.
So to respect the viewer, I’ve followed Scott’s lead. This blog will show you either the light
or dark theme depending on your settings. One place I diverged from Scott’s article & walkthrough
is in respecting the manual choice of the user in the UI. If you click light or dark mode, it’ll
persist and override your browser settings. I haven’t quite worked out the UX on how to let the user clear
their preferences out of localStorage
without running window.localStorage.removeItem('theme')
in the browser console.
To prevent having to fork and have my own snowflake copy of the theme, I added a partial that renders right after the HTML has loaded.
if (window.matchMedia) {
var match = window.matchMedia('(prefers-color-scheme: dark)')
toggleDarkMode(match.matches);
match.addEventListener('change', e => {
toggleDarkMode(match.matches);
})
function toggleDarkMode(state) {
// User has specified dark or light mode
if(window.localStorage && window.localStorage.getItem("theme")){
return
}
let body = document.querySelector("body")
if (state) {
body.classList.add("dark-theme")
} else {
body.classList.remove("dark-theme")
}
}
}