2020home

Dark Mode

It's not surprising that dark mode is the new fad in the town after Apple introduced the dark mode in MacOS. I decided to add a toggle button to switch to the dark theme on my blog.

Let's establish a few ground rules of engagement:

  1. The default theme of the blog must always be the light theme. For example, if the user's device does not define the prefers-color-scheme CSS rule then we apply the default theme.
  2. We must respect the mode the user's device is currently switched to and override the blog's theme to match that mode. For example, if the user's device is using the dark mode, then we apply the .dark theme to the blog and vice versa.
  3. We must always provide the user with an option to toggle between the light and the dark theme for the blog.
  4. If the user's device is running on dark mode and the user decides to switch to the light theme, then all subsequent pages should use the light theme, and vice versa.
  5. The behavior defined in #4 should reset when the tab or the browser window is closed.

Step 1

Define the light and dark theme for your site in CSS. Apply the .light class by default to the body of the document.

.light {
  --level-0: #fff;  --text-0: #000;
  --level-1: #eee;  --text-1: #333;
  --level-2: #ddd;  --text-2: #666;
}
.dark {
  --level-0: #111;  --text-0: #fff;
  --level-1: #222;  --text-1: #ccc;
  --level-2: #333;  --text-2: #999;
}

Step 2

Its now time to add a toggle button that will toggle the theme each time it is clicked.

<a role="button" 
   class="btn-toggle" 
   title="Toggle between Dark and Light theme">Light/Dark</a>

Step 3

We use sessionStorage instead of localStorage so that saved theme gets wiped out after the tab or window is closed. This covers the requirement #5.

<script>
  const btn = document.querySelector(".btn-toggle");
  const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");

  if(sessionStorage.getItem("theme") != null){
    document.body.className = sessionStorage.getItem("theme");
  }
  else if(prefersDarkScheme.matches){
    document.body.className="dark";
  }
  
  btn.addEventListener("click", function(e){
    if(document.body.className=="dark"){
      document.body.className="light";
      sessionStorage.setItem("theme","light");      
    }
    else{
      document.body.className="dark";
      sessionStorage.setItem("theme","dark");
    }
    e.preventDefault();
    return false;
  });
</script>
  • On first load, CSS will apply the theme based on the users device.
  • If the user toggles the theme, we update the class on the body and save the theme info in sessionStorage.
  • If the user navigates to a different page on the site, we read any saved theme info from the sessionStorage and apply if available.