Making a Darkmode for your distill site

Published

March 14, 2021

Join the Dark Side!

… we have cookies.

From: knowyourmeme

There are many motivations to adding a dark mode to your site. I just like it, when things look consistent. So I also want my site to reflect that. But because at the same time I am also not very good at making things look consistent, which is why I mostly outsource design choices as much as I can. Here, for example, this means that I took the color values for the dark theme from the amazing nord color palette.

But let’s get into the practical side! How do we add a dark theme to complement our light theme to our distill site?

Adding the button, css and java script

First, we want a button that a user can click on to change the theme. I opted for the adjust button from Font Awesome. There is not much to do here, because those are already available in distill. Open up your _site.yml file and add an icon to the navbar:

navbar:
  right:
    - icon: fas fa-adjust

While we are in this file, let’s also add the includes for the html file which will make the button work:

output:
  distill::distill_article:
    includes:
      after_body: "_after_body.html"

Note: I am omitting all the other things in our .yml file here and only show, what is being added. But I include the indentation-levels above the thing being added to show where to put it.

This is what _after_body.html looks like:

<script>
const darkmodeToggle = document.getElementsByClassName("fas fa-adjust")[0];
let theme = localStorage.getItem("theme");

if (!theme) {
  if (window.matchMedia("(prefers-color-scheme: dark)").matches ) {
    theme = "dark";
  } else {
    theme = "light";
  }
}
setTheme();

function switchTheme() {
  if (theme === "light") {
    theme = "dark";
  } else {
    theme = "light";
  }
  localStorage.setItem("theme", theme);
  setTheme();
  console.log(theme);
}

function setTheme() {
  if (theme === "dark") {
    document.body.classList.add('darkmode');
  } else {
    document.body.classList.remove('darkmode');
  }
}

darkmodeToggle.addEventListener('click', switchTheme)
</script>

Unfortunately, the only way I found to refer to the darkmode toggle icon in the navbar was by class name. I could not find a way to give it an id from _site.yml. However, this should be fine because the navbar is usually the first thing on the page and the script refers to the first element of class fas fa-adjust that it can find. It is also important to have this script be included after the body, so that the rest of the site can load first before the script tries to find the button. Typically you would do this using a script file and sourcing it with the option defer, but sourcing a script file doesn’t work here due to the way distill changes file-path’s between top-level sites and posts. This is why the complete script is in the html here. The script adds a class .darkmode to the html body (and removes it when toggled off). This choice is first based on browser preferences and then saved to local storage.

The last thing to modify is our theme.css to make use of this .darkmode class. For each thing we want to change about our theme when it get’s dark, we take the corresponding class and the darkmode class and add our styling e.g.

.darkmode d-article,
.darkmode d-appendix,
.darkmode body {
  background-color: black;
  color: white;
}

You can have a look at my theme.css file for inspiration on what thing you need to change (though the css could be way cleaner): https://github.com/jmbuhr/jmbuhr.github.io/blob/master/theme.css