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.
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:
body {
background: white;
color: #555;
}
a, a:link {
color: #639A67;
}
a:hover {
color: #205D67;
}
You’ll then define the custom properties as such:
: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:
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:
.funky {
--bg: hotpink;
--text-color: white;
--link-color: #B793E6;
--link-hover: #3532A7;
}
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:
background: linear-gradient(to right, #FFFB85, #5A3662); /* our fallback */
background: linear-gradient(to right, var(--top-grad1), var(--top-grad2));
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:
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:
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.
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.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!