Tuesday, March 28th 2023

Adding Dark Mode via CSS Variables

8 minutesTeddy Ni

You're trying to improve your app's design.

You're looking at popular examples, like Linear or Vercel, and you notice they all have one major thing in common:

They all support dark mode.

Why Dark Mode?

Dark mode has made a huge surge in popularity over the last couple of years for a very good reason.

  • Aesthetic. Dark backgrounds are elegant and modern. Colors and images pop out more, making your app look more engaging and polished.
  • Reduces eye strain. Reading is easier in low light with less strain because the device emits less light.
  • Energy-efficient. Less light means less energy consumption!

Great, you've decided you want to implement dark mode to give your users a delightful experience and make your app stand out.

But how do you do it? Do you have to code an if statement every time you use a color?

Implementing Dark mode

With the right framework and abstraction, implementing dark mode (or any other customizable theme) is actually pretty straight forward.

The rest of this blog post will outline how to properly abstract your CSS variables to easily implement consistent and flexible theme modes. We'll also go over some open-source frameworks that can streamline the process.

Migrate to CSS Variables

The first step is to ensure that you are using CSS variables for all of your colors.


In general, this is a good practice because it allows you to easily change your color palette without having to change every single instance of the color.

For example, instead of hard coding your colors like this:

.primary-button {
  background-color: #9f7aea;
  border: '1px solid #000000';

Define your colors as CSS variables in the :root selector, and consume them like constants:

:root {
  --primary-color: #9f7aea;
  --border-color: #000000;

.primary-button {
  background-color: var(--primary-color);
  border: '1px solid var(--border-color)';

An important note is that you'll want to name your CSS variables semantically. In other words, name them based on how they are used, rather than what they are.

For example, instead of naming #9f7aea Purple, we named it Primary in the above example because in different themes, this value might change.


You can actually reference CSS variables from Javascript inline styles too!

Define a Dark theme

Now that we have our CSS variables set up, we can create our dark theme. We'll do this by creating another set of the CSS variables we just defined.

But instead of defining them in :root, we'll define them in a new selector called :root[data-theme="dark"], and update the values to what we want them to be in our dark theme.

:root {
  --primary-color: #9f7aea;
  --border-color: #000000;

:root[data-theme="dark"] {
  --primary-color: #6B46C1;
  --border-color: #ffffff;

.primary-button {
  background-color: var(--primary-color);
  border: '1px solid var(--border-color)';

The beauty with this implementation is that the consuming code doesn't need to change at all. We could create infinite different number of themes and the consuming code would just work!

Toggling the Theme

The last step is to actually programmatically toggle the theme. We'll do this by setting the data-theme attribute on the root document element.

document.documentElement.setAttribute('data-theme', 'dark');
document.documentElement.setAttribute('data-theme', 'light');

And with that, you have a functioning dark theme app!


There are a few frameworks that can help you implement dark mode in your app. Here are a few of the most popular ones:


If you're looking for a lightweight, library-agnostic solution, check out our open-source solution Mirrorful.

At Mirrorful, we want to empower you to build your own design system and avoid being locked into a framework.

If you're interested in using Mirrorful to add dark mode to your app, try out our online demo or install our NPM package.

We're working on some pretty cool stuff, so make sure to join the discussion in our Slack community or check out our open-source Github!



Backed by



Sign InSlack

© Mirrorful 2023