Theme your Web App with CSS Variables

If you’re building websites in 2020 you MUST add an option to toggle light 🌞 dark 🌑 mode - at the very least. You can really impress your users by adding a button to toggle multiple themes. That might sound complicated, but user-controlled themes are actually very easy to implement in sites the utilize CSS variables. The snippet below demonstrates multiple methods for theming a website dynamically at runtime.

Option 1 - Media Query prefers-color-scheme

How do you get a user’s preferred color scheme with CSS?

As of 2020, it is possible in most browsers to run a media query for the user’s preferred color scheme at the system level. If their macbook is set to dark mode, then your app can automatically run with a dark theme. In the code below, we change CSS variables at the root of the application based on the result of the media query.

Light/Dark CSS

file_type_css style.css
@media (prefers-color-scheme: dark) {
    :root {
        --text-color: #b6b6b6;
        --background: #ececec;
    }
}

@media (prefers-color-scheme: light) {
    :root {
        --text-color: #1f1f1f;
        --background: #000000;
    }
}

body {
    color: var(--text-color);
    background: var(--background);
}

Option 2 - Toggle CSS Variables

How do you toggle multiple themes with CSS variables?

The Media Query above is great for light/dark mode, but does not help sites with multiple custom themes. To handle that feature, we will need a little bit of JavaScript. Notice how the demo below allows the user to cycle between multiple themes by clicking a button.

Multiple CSS Themes

First, define a set of theme values and use them throughout your CSS code.

file_type_css style.css
.dark {
  --text-color: #b6b6b6;
  --background: #ececec;
}

.light {
  --text-color: #1f1f1f;
  --background: #000000;
}

.solar {
  --text-color: #576e75;
  --background: #fdf6e3;
}

body {
    color: var(--text-color);
    background: var(--background);
}

In this example, the theme is attached to the <body>, but feel free to use it on any element that is theme-able.

file_type_html index.html
<body class="dark"></body>

JavaScript Theme Toggle

The code below provides map that creates a circular list, so the user can toggle themes in an infinite loop by clicking one button. The user’s preferred theme is stored in the browser’s local storage - this allows it to remain active between browser refreshes or visits from other windows.

file_type_js_official app.js
// Define which theme should load next
const themeMap = {
  dark: 'light',
  light: 'solar',
  solar: 'dark'
};

// Load the existing theme in local storage
const theme = localStorage.getItem('theme');
const bodyClass = document.body.classList;
theme && bodyClass.add(theme);

// Change the theme on a button click
function toggleTheme() {
  const current = localStorage.getItem('theme');
  const next = themeMap[current];

  bodyClass.replace(current, next);
  localStorage.setItem('theme', next);
}

document.getElementById('themeButton').onclick = toggleTheme;

Questions?

Ask questions via GitHub below OR chat on Slack #questions