3 ways to implement dark mode on websites
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.
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.
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>