A simple React Theme Component using CSS variables

At Trabe we had to create a component library with multiple look and feels for some client. This is the solution we came up with.

Lucas Andión
Trabe
3 min readDec 17, 2018

--

Photo by Finan Akbar on Unsplash

Our needs

  • We like to use CSS Modules so the solution should be compatible.
  • We should be able to show Components with different themes at the same time.
  • It should require minimal tooling.

The solution

Using CSS variables to customize our CSS files, and writing our components as we would normally do.

For example, a small Button component could look like this:

A simple button component

But instead of having a button.css like this:

Standard CSS file following BEM conventions

We would have:

The same CSS using vars

Note that we use BEM conventions, adapting them to our liking, but the styles themselves are self explanatory.

Where do we get those vars from? We inject them on a wrapper element that surrounds the components we want to style.

How do we inject them? With a Theme Component that gets the variables as props, creates a div that acts as a wrapper and passes them on its style prop.

We could then have some custom themes to store those variables and export them within the Theme component itself, like you see here:

Theme component

Our two themes could look like this Jedi theme:

Jedi theme under the /themes folder

Or this Sith theme:

Sith theme under the /themes folder

Now, if we want to show a Button using either theme we just have to wrap it on a Theme with the according variables:

This should look more or less like this (if you don’t have the Sith Font and the Jedi Font installed).

Our button component in Jedi & Sith themes

If you want a Jedi app you just have to wrap all your app on a Jedi theme. You can also do it on smaller portions of it.

Sometimes you may even want to see your component in every theme you have. We do so in our Docz documentation with a little helper that renders a component in every theme available.

The gotchas

If you like this approach and you want to use it you have to plan your themes accordingly.

For example: if you want, say, rounded borders on one of theButton themes you will have to set a border-radius property on your styles, and remember to set it to none on all the themes that have squared borders.

You will also have to wrap all the components that support theming. Things like modals and everything outside a Theme wrapper would look unstyled.

If your var files grow a lot, FOUC could become a problem at some point but we had none as of time of writing.

Conclusion

Maybe all this is overkill, maybe it has no sense at all, but existing solutions did not fit our needs and we like this simple, clean approach.

You may feel uncomfortable using CSS variables for theming, but they are widely supported and they let you change most visual aspects of your components.

We’d love to hear your thoughts and solutions to this problem.

--

--

Lucas Andión
Trabe

Galician. Software developer @trabe. Bike lover, beer enthusiast, mad traveler, beagle friend, surfer wannabe — https://andion.github.io