How to theme with CSS variables
Tags: css, webdev, cssvariables, frontend
Published: 2019-01-21 10:30:18

---
title: How to theme with CSS variables
published: true
cover_image: https://assets.browserlondon.com/app/uploads/2018/12/css-themeing.png
tags: CSS,webdev,CSSvariables,front-end
canonical_url: https://www.browserlondon.com/blog/2019/01/15/css-variables-theming/
---

Some time back we wrote a popular article about [using Sass maps](https://www.browserlondon.com/blog/2015/04/07/theming-with-sass/) and a little bit of [BEM](http://getbem.com/) to tackle the tricky front-end task of creating CSS themes without the need to do battle with specificity.

Three years on, however, the CSS tools we have at our disposal have advanced hugely and there is now a more flexible and future-proof way of solving this issue.

## Enter CSS variables

You might also have heard these referred to as CSS custom properties. Much like the name suggests, they allow you to store references to values and make use of them down the line:

First, we store a value:

```
:root {
  --green-bright: #27efa1;
}
```

… then we make use of it:

```
background-color: var(--green-bright);
```

At this point, CSS variables don’t look much different to variables in Sass, but there’s one really neat difference – CSS variable values can be reassigned.

With this knowledge, we can do some really interesting stuff. For example, let’s say you wanted to theme an individual component – I’ll use the example of a generic section for housing content.

First, we set some variables:

```
:root {
  --sectionBG: var(--white);
  --sectionText: var(--grey-dark);
  --linkColor: var(--green-bright);
  --titleColor: var(--green-bright);
}
```

Then scaffold out our default section styling making use of these variables:

```
section {
  background-color: var(--sectionBG);
  color: var(--sectionText);
  padding: 7rem 0;

  h2 {
    color: var(--titleColor);
  }

  a {
    color: var(--linkColor);
  }

  .btn {
    &:hover {
      background-color: var(--linkColor);
      border-color: var(--linkColor);
      color: var(--sectionText);
    }
  }
}
```

Now when we want to create an alternate theme we can use a BEM modifier class to reassign these variables:

```
.section--grey {
  --sectionBG: var(--grey-dark);
  --sectionText: var(--grey-light);
  --titleColor: var(--white);
}
```

So with almost no additional CSS we’ve created a completely new theme for our section. Cool!

## Extrapolating CSS variables further

With this trick in mind, it’s easy to imagine how we might extend the idea further – we might, for example, create a bunch of generic variables such as `--theme-primary` and `--theme-accent` and, with some careful planning and use of the cascade, we’d be able to re-theme entire applications just by reassigning them.

You could also create different themes on a page-by-page basis by injecting a `style` tag into the `head` which reassigns these variables on different pages – we do something like this on the Browser London website. This is particularly nice because it means you don’t have to predefine themes ahead of time – they can be user-generated and stored in a database (again, something we use on our site).

One of my favourite things about this approach is that it embraces some of CSS’s core features rather than fighting against them. Doing so is not only good for reducing code size and complexity, but it also encourages consistency in UI because components feel much more related to each other rather than being isolated blocks. Another useful advantage is that, because CSS variables are native to the browser, you can experiment with them on the fly in dev tools. I find this really useful for testing which colour from my palette is going to work best in a particular scenario.

![Css variables example](https://assets.browserlondon.com/app/uploads/2018/12/CSS-theming-1-copy-300x160.png)

## Things to consider

As you can probably tell I’m a big fan of this technique, but as with all modern CSS there are things to consider. Chief amongst them is a front-end dev’s good friend – browser support.

At the time of writing [just over 87.5% of browsers globally support CSS variables](https://caniuse.com/#search=custom%20properties), which is really pretty good, but it still leaves 12.5% unaccounted for (including, as you might expect, all versions of Internet Explorer). Given we’re likely to be using them for fundamental parts of our application rather than [progressive enhancement](https://www.browserlondon.com/blog/2017/03/14/performance-benefits-progressive-enhancement/) we need a good way of dealing with this.

At the moment I’m using [PostCSS](https://postcss.org/) with the [postcss-custom-properties plugin](https://github.com/postcss/postcss-custom-properties) in my build process, which basically adds a new CSS property above your variable usage with the compiled value of that variable.

![Css variables](https://assets.browserlondon.com/app/uploads/2018/12/CSS-theming-2-copy-300x78.png)

This seems like a fairly good solution but still isn’t ideal, and I’ve definitely had cases where I’ve reassigned a variable multiple times and the plugin has compiled it down to the wrong value. In practice, this has resulted in things like a button being a different colour in IE to other browsers. It’s up to you to decide how important things like this will be for your product, and there’s definitely a counter-argument that perhaps I’ve been making things too complicated in order for this to happen in the first place.

![Css variables guide](https://assets.browserlondon.com/app/uploads/2018/12/CSS-theming-3-copy-300x86.png)

These hiccups aside I think this is a fantastic way to embrace modern CSS and simplify our styling process. Whilst this article was limited to theming you can find so many more use cases for custom properties, and hopefully you’ll enjoy the flexibility they afford you.

----

The post [How to theme with CSS variables](https://www.browserlondon.com/blog/2019/01/15/css-variables-theming/) appeared first on [Browser London](https://www.browserlondon.com).