Mohit Khare
Mohit Khare
Product Engineer @ Gojek | Blogs about tech, productivity and life.

Add Dark mode to websites

Add Dark mode to websites

I am a huge fan of dark mode — from editors, terminals to websites, I have most of stuff customized for dark mode. Now most of the website and apps support a dark mode.

Dark Mode is ❤️️

One of the typical case is using your mobile and laptops at night and you don’t want lights on — relatable? Yeah, It is such a pain to use light mode in low light scenarios. Now you want to add it to your personal website and side projects too right? Let’s learn how to do that!

Using Media Queries

A new media queryprefers-color-scheme is added in Media Queries 5 specifications. You can simply set your css based on whether the user’s preferred light/dark mode.

Here, I just show a simple example, where I am setting background-color and color property for both the modes.

1
2
3
4
5
6
7
8
9
10
11
12
13
@media (prefers-color-scheme: dark) {
  html {
    background-color: black;
    color: white;
  }
}

@media (prefers-color-scheme: light) {
  html {
    background-color: white;
    color: black;
  }
}

Drawback

Although this works for most of the browsers like Chrome( ≥76), Safari( ≥12.1) and Firefox(≥67). Just in case you are worried about people still using older versions then you might want to implement some custom CSS and JS way described below.

Also, if you are still using IE, then only God can help you 😛


Using Custom CSS and JS

You probably have seen sites with those toggle button to switch between light and dark modes. That looks cool! Well, we are going to implement the same cool thing 😎

Let’s add a simple div with this toggle. You can use a button or any other element.

Light theme demo

1
2
3
<div class="switch" id="theme-toggle">
  <div class="slider round"></div>
</div>

The code above is only for the toggle. Now, let’s add some css for the light theme.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/* Add this in light_theme.css */
.switch {
  _display_: flex;
  _height_: 36px;
  _position_: relative;
  _width_: 70px;
}

.slider {
  _background-color_: #fff;
  _border_: 1px solid #000;
  _bottom_: 0;
  _cursor_: pointer;
  _left_: 0;
  _position_: absolute;
  _right_: 0;
  _top_: 0;
  _transition_: 0.4s;
}

.slider:before {
  _background-color_: #333;
  _border_: 1px solid #000;
  _bottom_: 3px;
  _content_: "";
  _height_: 26px;
  _left_: 4px;
  _position_: absolute;
  _transition_: 0.4s;
  _width_: 26px;
  _z-index_: 421;
}

.slider.round {
  _border-radius_: 34px;
}

.slider.round:before {
  _border-radius_: 50%;
}

Similarly, let’s add css for the dark theme —

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/* Add this in dark_theme.css */
.switch {
  _display_: flex;
  _height_: 36px;
  _position_: relative;
  _width_: 70px;
}

.slider {
  _background-color_: #fff;
  _border_: 1px solid #000;
  _bottom_: 0;
  _cursor_: pointer;
  _left_: 0;
  _position_: absolute;
  _right_: 0;
  _top_: 0;
  _transition_: 0.4s;
}

.slider:before {
  _background-color_: #333;
  _border_: 1px solid #000;
  _bottom_: 3px;
  _content_: "";
  _height_: 26px;
  _right_: 4px;
  _position_: absolute;
  _transition_: 0.4s;
  _width_: 26px;
  _z-index_: 421;
}

.slider.round {
  _border-radius_: 34px;
}

.slider.round:before {
  _border-radius_: 50%;
}

Once, we have this css added. Don’t forget to include them in your html.

1
2
3
4
5
6
7
/* Include in your html */
<link
  id="theme"
  rel="stylesheet"
  type="text/css"
  href="css/light_theme.css"
/>

We don’t need to add dark_theme.css since we will add it via custom JS.

You should be able to see a working light theme and a toggle. But, the theme doesn’t change!!

Let’s make that toggle work now! Add javascript to load custom css file based on the theme mode selected. We use localstorage to save user preferences for the theme. We don’t want him to click toggle again and again.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
document.addEventListener("DOMContentLoaded", () _=>_ {
  _const_ themeStylesheet = document.getElementById("theme");
  _const_ storedTheme = localStorage.getItem("theme");
  if (storedTheme) {
    themeStylesheet.href = storedTheme;
  }
  _const_ themeToggle = document.getElementById("theme-toggle");
  themeToggle.addEventListener("click", () _=>_ {

  // if it's light -> go dark

  if (themeStylesheet.href.includes("light")) {
    themeStylesheet.href = window.location.origin + "/<filepath-to>/dark_theme.css";
  } else {
    // if it's dark -> go light
    themeStylesheet.href = window.location.origin + "/<filepath-to>/light_theme.css";
  }

    // save the preference to localStorage
    localStorage.setItem("theme", themeStylesheet.href);
    reloadCss()
  });
});

I use a reloadCss() to refresh css files without actual page reload. You can also refresh the page with window.location.reload()

Drawback — This method basically iterates over all CSS links.

1
2
3
4
5
6
7
8
_function_ reloadCss() {
 _var_ links = document.getElementsByTagName("link");
 for (_var_ cl in links) {
 _var_ link = links[cl];
 if (link.rel === "stylesheet")
 link.href += "";
 }
}

Result

Check the Live demo

PS: If you use frameworks like React, Vuejs then there are lot more and better ways to implement this.

Resources

Time to add beautiful dark mode to your websites 🚀

Show your implementations in comments 👇

Liked the article? Consider supporting me ☕️


Feel free to suggest improvements ✔️

I hope you learned something interesting and new. Don’t miss out on the latest blogs — Subscribe now

Interested in more technology, productivity and life stuff? I share updates/knowledge almost daily on Twitter.

Reach out to me at https://mohitkhare.me/

Keep exploring 🔎 Keep learning 🚀

comments powered by Disqus