Create a Dark/Light Mode Toggle using JavaScript & LocalStorage 💫
Zoe
Posted on July 23, 2023
Hi There! 👋
In this Article, I want to show you how you can create a simple light / dark mode toggle using JavaScript and LocalStorage.
Here is one example made using Toggle; Try Clicking the top right icon to see the themes change!
(Just a friendly reminder that you can also check the pure HTML / CSS code by clicking "view compiled" on CodePen!)
Let's get started!
The HTML
<!-- dark theme toggle -->
<label id="theme-switch" class="theme-switch" for="checkbox_theme">
<input type="checkbox" id="checkbox-theme">
<label for="checkbox-theme" class="fas"> </label>
</label>
<!-- Some general elements -->
<div class="wrapper">
<h1>Dark Theme Toggle</h1>
<p>Click the top right icon to switch modes</p>
</div>
We will be using the checkbox property and Font Awesome Icons for the toggle switch. Basically, we will set a different icon if the checkbox is checked using CSS!
CSS
Let's first set up the document color scheme using CSS variables;
One for light mode (default), and another for dark mode.
Feel free to adjust the colors to your own preference!
/* light mode */
:root {
--background: #f6f6f6;
--card: #ffffff;
--border: #cccccc;
--table-header: #e6e6e6;
--primary-text: #000000;
--secondary-text: #212121;
}
/* dark mode */
[data-theme="dark"] {
--background: #121212;
--card: #181818;
--border: #212121;
--table-header: #212121;
--primary-text: #f6f6f6;
--secondary-text: #9ca3af;
}
Now let's add some styles to the checkbox!
the content: "\f186";
will show the moon icon on Font Awesome, which we will be using for dark mode. Similarly, we will use the lightbulb icon for light mode.
#checkbox-theme {
display: none;
}
/* light mode icon */
#checkbox-theme + label:before {
content: "\f186";
font-size: 20px;
cursor: pointer;
position: fixed;
top: 10px;
right: 10px;
}
/* dark mode icon */
#checkbox-theme:checked + label:before {
content: "\f0eb";
font-size: 20px;
cursor: pointer;
position: fixed;
top: 10px;
right: 10px;
}
And here are some general stylings you can add to your page for testing purposes 😁
body {
font-family: "Roboto", sans-serif;
background-color: var(--background);
color: var(--primary-text);
text-decoration: none;
}
a {
text-decoration: none;
color: var(--primary-text);
}
a:hover {
text-decoration: none;
}
.wrapper {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.wrapper h1 {
font-size: 50px;
}
.wrapper p {
font-size: 17px;
margin-top: 0;
}
JavaScript
Now let's write some JavaScript!
The following code will be the main part of our code; It will call the switchTheme
function when the user checks/unchecks the checkbox!
Listen for change in checkbox
//listener for changing themes
toggleSwitch.addEventListener('change', switchTheme, false);
We want the switchTheme()
function to do 3 main things :
One, Change the data theme to light or dark
document.documentElement.setAttribute('data-theme', 'dark');
Two, Switch the checkbox icon
toggleSwitch.checked = true;
And finally, save the theme to local storage.
localStorage.setItem('theme', 'dark');
Strictly speaking, the third part (localStorage) is not really necessary to achieve this, but we don't want the users to have to switch the theme every time they refresh the website right? So let's utilize localStorage to save the user's preference! We will get back to this on the next part.
Getting back, here is what the complete switchTheme()
function looks like :
function switchTheme(e) {
if (e.target.checked) {
document.documentElement.setAttribute('data-theme', 'dark');
toggleSwitch.checked = true;
localStorage.setItem('theme', 'dark');
}
else {
document.documentElement.setAttribute('data-theme', 'light');
toggleSwitch.checked = false;
localStorage.setItem('theme', 'light');
}
}
Saving User's Preference to LocalStorage
Let's get back to LocalStorage. To improve user experience, we want to
- Check the user's OS settings to automatically preset the theme
- Check localStorage to save user's preference if the user changed the theme
So let's add another function named detectColorScheme()
to achieve this!
1. Checking the user's OS settings
This will do the trick!
if(window.matchMedia("(prefers-color-scheme: dark)").matches) {
//OS theme setting detected as dark
var theme = "dark";
However, some browsers do not support matchMedia method (Click here to check browser support), so let's consider that as well.
if(!window.matchMedia) {
// matchMedia method not supported
return false;
}
else if(window.matchMedia("(prefers-color-scheme: dark)").matches) {
//OS theme setting detected as dark
var theme = "dark";
}
So for example, if you are using dark mode on your mac, the website will automatically switch the display to dark mode.
Checking LocalStorage to override OS theme settings
But what if a dark mode user wants to see the website in light mode, and changes it? Let's also save this preference to LocalStorage!
if(localStorage.getItem("theme")){
if(localStorage.getItem("theme") == "dark"){
var theme = "dark";
}
}
Here is the complete code for detectColorScheme()
!
function detectColorScheme(){
//default is set to light mode
var theme="light";
//local storage is used to override OS theme settings
if(localStorage.getItem("theme")){
if(localStorage.getItem("theme") == "dark"){
var theme = "dark";
}
}
else if(!window.matchMedia) {
// matchMedia method not supported
return false;
}
else if(window.matchMedia("(prefers-color-scheme: dark)").matches) {
//OS theme setting detected as dark
var theme = "dark";
}
// if dark theme is preferred, set document with a `data-theme==dark` attribute
if (theme=="dark") {
document.documentElement.setAttribute("data-theme", "dark");
}
}
And here is the complete JS code 🎉
$(document).ready(function () {
const toggleSwitch = document.querySelector(
'#theme-switch input[type="checkbox"]'
);
function detectColorScheme() {
var theme = "light";
//local storage is used to override OS theme settings
if (localStorage.getItem("theme")) {
if (localStorage.getItem("theme") == "dark") {
var theme = "dark";
}
} else if (!window.matchMedia) {
return false;
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
var theme = "dark";
}
if (theme == "dark") {
document.documentElement.setAttribute("data-theme", "dark");
}
}
detectColorScheme();
function switchTheme(e) {
if (e.target.checked) {
localStorage.setItem("theme", "dark");
document.documentElement.setAttribute("data-theme", "dark");
toggleSwitch.checked = true;
} else {
localStorage.setItem("theme", "light");
document.documentElement.setAttribute("data-theme", "light");
toggleSwitch.checked = false;
}
}
toggleSwitch.addEventListener("change", switchTheme, false);
if (document.documentElement.getAttribute("data-theme") == "dark") {
toggleSwitch.checked = true;
}
});
That's it! 🥳
Thanks for reading, and happy coding! ❤️
If you have any thoughts or questions, feel free to leave a comment! 😊
Posted on July 23, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.