Table of Contents
Introduction
You may have noticed that on many websites you can now toggle between dark and light themes. This is often done using CSS custom properties (aka CSS variables). In this tutorial you'll see how you can achieve something similar using only CSS and a touch of JavaScript. To learn more about how this code works, check out our series content on Javascript or HTML.
Step 1 — Creating the CSS Variables
The power of custom properties in CSS really shines here because, unlike with variables defined using a CSS preprocessor, these values are dynamic; their values can be changed or overwritten at any point in time in response to user input. When the value of a variable is changed or overwritten, all elements that use the variable will automatically reflect the change.
First you'll have to do a bit of work and extract all the colors that you want to use in your CSS custom properties. Let's say you're starting with the following styles:
[label style.css]
body {
background: white;
color: #555;
}
a, a:link {
color: #639A67;
}
a:hover {
color: #205D67;
}
You'll then define the custom properties as such:
[label style.css]
:root {
--bg: white;
--text-color: #555;
--link-color: #639A67;
--link-hover: #205D67;
}
With this in place, you can now change your CSS rules to something like the following:
[label style.css]
body {
background: var(--bg);
color: var(--text-color);
}
a, a:link {
color: var(--link-color);
}
a:hover {
color: var(--link-hover);
}
Applying the theme involves adding a class to the body element, so you'll define the theme's colors under that class name. Here we'll call the class <^>funky<^>. Simply make sure to define an override color for all colors should change:
[label style.css]
.funky {
--bg: hotpink;
--text-color: white;
--link-color: #B793E6;
--link-hover: #3532A7;
}
Step 2 — Adding Fallbacks for Older Browsers
Support for CSS custom properties is pretty good, but you'll most likely want to include fallbacks for users that are on older browsers.
Let's say that we have an element that should have a linear-gradient background with colors defined as custom properties. You provide hard-coded colors first, and older browsers will ignore the version that they don't understand:
[label style.css]
background: linear-gradient(to right, #FFFB85, #5A3662); /* our fallback */
background: linear-gradient(to right, var(--top-grad1), var(--top-grad2));
Step 3 — Toggling Our Theme
We only need a very minimal amount of JavaScript to add an event listener on an element that acts as the toggle button between the two themes.
Here the toggle button has the <^>toggle-theme<^> class and we use <^>document.querySelector<^> to get a reference to that element:
[label app.js]
let toggle = document.querySelector('.toggle-theme');
toggle.addEventListener('click', function(e) {
e.preventDefault();
if (document.body.classList.contains('funky')) {
// Turning the theme off:
document.body.classList.remove('funky');
// Reverse logic on the button text, so that users can turn
// the theme back on:
toggle.innerText = 'Turn theme on';
} else {
document.body.classList.add('funky');
toggle.innerText = 'Turn theme off';
}
});
This does the trick to toggle between the two themes. We can do better and also add/remove an item to localStorage at the same time so that our theme gets applied automatically when the page loads:
[label app.js]
let toggle = document.querySelector('.toggle-theme');
// Turn the theme off if the 'funky' key exists in localStorage
if (localStorage.getItem('funky')) {
document.body.classList.add('funky');
toggle.innerText = 'Turn theme off';
}
toggle.addEventListener('click', function(e) {
e.preventDefault();
if (document.body.classList.contains('funky')) {
document.body.classList.remove('funky');
toggle.innerText = 'Turn theme on';
localStorage.removeItem('funky');
} else {
document.body.classList.add('funky');
toggle.innerText = 'Turn theme off';
localStorage.setItem('funky', true);
}
});
You can use this small snippet and CSS variables to create themed websites like this, with dark-modes, light-modes, and more.
Conclusion
In this tutorial you created a themed website that has a dark and light mode. To learn more about how this code works, check out our series content on Javascript or HTML.