Tutorial

How To Create a Dark-Mode Theme Using CSS Variables

CSS

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:

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:

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:

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:

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:

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:

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:

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.

Creative Commons License