An Interactive Tutorial on Adding Dark Mode to any Website

Published on 02 Jun 2021 | Updated on 24 May 2022
Written by Pranav Chakkarwar
7 minutes to read

Adding a dark mode is a great way to make any website visually appealing while making it more accessible. This article will guide you to add a toggle switch for dark theme on any website. Read till the end to avoid missing any important details. If I miss something relevant, please contact me.

Take a look at a recorded demo!

gif demo of theme testing

The first technique is to use a button to activate and deactivate the dark mode.

Click the lightning bolt to try it out.



Hello, here's some text to demonstrate changing of styles using a toggle. Your preference will be saved in the browser's local storage as well. To test it, try refreshing the page.

To modify the colors of the text, background, and svg fill, we’ll use CSS variables.

.init {
  background: #ffffff !important;
  color: #000000 !important;
  --lightboltsvg: #fff348 !important;
  transition-duration: 0.5s;
}

body {
  background: #000000;
  color: #ffffff;
  padding: 3rem;
  border-radius: 0.25rem;
  --lightboltsvg: #505050;
  text-align: center;
  transition-duration: 0.5s;
}

In the html, make sure the element with the id #toggle-button is inside the element with the id #themebuttondiv.

<body id="themebuttondiv" class="themebuttondiv init">
  <div id="toggle-btn">
    <svg
      id="lightboltsvg"
      height="50"
      width="50"
      fill="var(--lightboltsvg)"
      viewBox="0 0 512 512"
    >
      <g>
        <g>
          <polygon
            points="426.667,213.333 288.36,213.333 333.706,0 148.817,0 85.333,298.667 227.556,298.667 227.556,512 		"
          />
        </g>
      </g>
    </svg>
  </div>
  <br /><br />
Hello, here's some text to demonstrate changing of styles using a toggle.
Your preference will be saved in the browser's local storage as well.
To test it, try refreshing the page. 
</body>

Coming to JavaScript, we’ll first define some constants in JavaScript.

const themetoggleexample = document.getElementById("toggle-btn");
themediv = document.getElementById("themebuttondiv");
const themetogglestore = localStorage.getItem("themetoggleexample");

To detect the preferred theme on each page load, we’ll use the browser’s local storage API to save an user’s preference locally. This will come in handy if an user navigates to another page.

A simple if statement will get the job done.

if (themetogglestore) {
  themediv.classList.remove("init");
}

The page will load initially with a light theme set by the init class. Whenver an user changes their theme, we need to check if the init class is present in the body tag. If it does, we’ll remove it and save the choice by storing a value in the local storage of the browser.

If an user decides to change the theme again, the if statement will render false but the else statement will restore the init class back to the body tag and delete the custom preference from the browser’s local storage.

themetoggleexample.onclick = () => {
  if (themediv.classList.contains("init")) {
    themediv.classList.remove("init");
    localStorage.setItem("themetoggleexample", "theme-dark");
  } else {
    themediv.classList.add("init");
    localStorage.removeItem("themetoggleexample");
  }
};

The complete javascript is quite easy to understand.

const themetoggleexample = document.getElementById("toggle-btn");
themediv = document.getElementById("themebuttondiv");
const themetogglestore = localStorage.getItem("themetoggleexample");

if (themetogglestore) {
  themediv.classList.remove("init");
}

themetoggleexample.onclick = () => {
  if (themediv.classList.contains("init")) {
    themediv.classList.remove("init");
    localStorage.setItem("themetoggleexample", "theme-dark");
  } else {
    themediv.classList.add("init");
    localStorage.removeItem("themetoggleexample");
  }
};

Another technique is to automatically adjust to an user’s preference.

We’ll use simple CSS Media Queries to identify an user’s preference from the browser’s settings.

Hello, here's some text to demonstrate the use of CSS media queries. To see the style update, change your theme configuration. No reload requried :)

Test it using the Firefox inspect mode.

find the toggle in Firefox inspect mode

For Chromium-based browsers, it’s a two-step process.

find the toggle in chrome step one

find the toggle in chrome step two

The CSS is quite straightforward and does not require any JavaScript.

:root {
      background: white;
      color: black;
    }

    @media (prefers-color-scheme: dark) {
    :root {
      background: black;
      color: white;
    }
  }
}

If you don’t need to give users a choice specific to your website, this method is ideal.

We can combine multiple approaches to make the design user-friendly.

To showcase the use of multiple approaches, I’ll take the example of an user with JavaScript turned off.

We’ll utilize the noscript html tag to check if JavaScript is turned off and use CSS media queries to determine an user’s preference from the browser’s settings. Cool! isn’t it?

<noscript>
  <style>
    .init {
      background: #ffffff !important;
      color: #000000 !important;
      --lightboltsvg: #fff348 !important;
    }
    @media (prefers-color-scheme: dark) {
      .init {
        background: #000000 !important;
        color: #ffffff !important;
        --lightboltsvg: #505050 !important;
      }
    }
  </style>
</noscript>

Taking it further with the dark mode.

We can geolocate an user or might use the user’s browser time to define a preference seamlessly and apply the theme. The JavaScript for detecting the time zone might look like…

var date = new Date();
var offset = date.getTimezoneOffset();
console.log(offset);

These approaches, however, may come with a number of drawbacks.

The whole code is given below. It may not be pristine, but it is certainly usable.

<body id="themebuttondiv" class="themebuttondiv init">
  <style>
    .init {
      background: #ffffff !important;
      color: #000000 !important;
      --lightboltsvg: #fff348 !important;
    }

    body {
      background: #000000;
      color: #ffffff;
      padding: 3rem;
      border-radius: 0.25rem;
      --lightboltsvg: #505050;
      text-align: center;
    }
  </style>

  <div id="toggle-btn">
    <svg
      id="lightboltsvg"
      height="50"
      width="50"
      fill="var(--lightboltsvg)"
      viewBox="0 0 512 512"
    >
      <g>
        <g>
          <polygon
            points="426.667,213.333 288.36,213.333 333.706,0 148.817,0 85.333,298.667 227.556,298.667 227.556,512"
          />
        </g>
      </g>
    </svg>
  </div>
  <br /><br />
  Hello, here's some text to demonstrate changing of styles using a toggle. Your
  preference will be saved in the browser's local storage as well. To test it,
  try refreshing the page.
  <br /><br /><br />
  Also, try disabling script and change your theme preference through the
  browser to see the magic!

  <script>
    const themetoggleexample = document.getElementById("toggle-btn");
    themediv = document.getElementById("themebuttondiv");
    const themetogglestore = localStorage.getItem("themetoggleexample");

    if (themetogglestore) {
      themediv.classList.remove("init");
    }

    themetoggleexample.onclick = () => {
      if (themediv.classList.contains("init")) {
        themediv.classList.remove("init");
        localStorage.setItem("themetoggleexample", "theme-dark");
      } else {
        themediv.classList.add("init");
        localStorage.removeItem("themetoggleexample");
      }
    };
  </script>

  <noscript>
    <style>
      .init {
        background: #ffffff !important;
        color: #000000 !important;
        --lightboltsvg: #fff348 !important;
      }
      @media (prefers-color-scheme: dark) {
        .init {
          background: #000000 !important;
          color: #ffffff !important;
          --lightboltsvg: #505050 !important;
        }
      }
    </style></noscript
  >
</body>

Hey Hooman! 😺

I don't display ads or run trackers. This blog is supported by people like you.

👋 Say hello
📖 Read more articles
Buy me a coffee
🚀 Hire me as a freelancer

Get Interesting Articles in Your Inbox 📨

or grab the feed