This post is outdated
In less than a year almost everything in this post has become outdated. Check out my new guide to implementing dark mode on a static site.
The internet is finally viewing the ability to switch back and forth between a dark theme or night mode and a light mode as an important accessibility feature. It’s about time. Staring at an overly illuminated screen all day is hard on the eyes, and trying to reduce evening light exposure has worked wonders for my sleep quality.
If you have a static site—my blog is built with Jekyll, but this is same concept if you use Hugo or Gatsby, you can’t use the server to change your CSS from the backend to switch back and forth between light and dark modes.
There’s three ways to change CSS on the front end so that whoever is reading a site will still in the color mode they selected:
- Cookies. A no go for me because the EU cookie thing is annoying.
- URL Parameters. I got this to work, but URLs are clunky looking and this sometimes breaks navigation to different parts of the same page.
- Local Storage. The clear winner: unnoticeable to readers and works well with the new
To be clear I wanted a switch that allows readers to select whichever color mode they want, and that mode needs to not revert to the default when someone navigates around the site. Furthermore, I didn’t want a flash of either black or white when moving between pages.
This meant that I needed a button that triggered a script to change the page’s CSS and add local storage telling future page loads which color scheme to use.
On my first attempt, I used two CSS files and swapped them out based on the preferred color scheme. This caused flashes of white or black when moving between pages in Firefox and Chrome. This is a common shortcoming of a lot of sites with dark mode toggles.
The solution is simple enough: use a single CSS file with variables. Here’s what my CSS looks like:
Of course, when you specify the colors for various elements in your CSS use the variables and not absolute values!
The last bit of CSS is adding a way to detect whether a site visiter prefers dark mode:
I put a simple button at the top of each page on my site:
At the very top of the page, I inserted a tiny script to check if dark mode has already been entered into local storage. If you run this at the end of the page, you’ll get a white flash when navigating between posts.
At the end of each page I inserted this script:
This script checks if a visitor prefers dark mode, and if so applies dark mode and notes it in local storage. If someone clicks the button, the mode gets changed and local storage updated accordingly. Additionally, the text of the button is updated to match the current color mode.
Like magic, you now have a dark mode toggle that works on a static site. You can have fun with this and add toggles for other things like sans-serif or serif fonts.