Interactive Tutorial on Adding Dark Mode to Any Website

Written by Pranav Chakkarwar
Published on 02 Jun 2021 & updated on 03 Jun 2022

Why add dark mode?

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. Read till the end to avoid missing any important details. If I miss something relevant, please contact me.

Toggle dark mode using a button

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");
  }
};

Adjust to the 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 using Dev tools (Crtl + Shift + I). No reload requried :)

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;
    }
  }

Combining both approaches

To showcase the use of a combined approach, 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

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.

Certainly usable code

<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>

Reply via Email

click to reveal

My thoughts, in your Inbox!

Your data will be handled as per my website's newsletter policy if you subscribe using your email address.

Other options to subscribe >