Theming Web Apps with SASS

Dmitry Borody
3 min readFeb 22, 2017

--

Need to support multiple color themes in your app? Here’s a simple way to do it in SASS.

However there are many ways of doing theming in SASS (a bunch of them is discussed here), the approach I’m talking about here has certain advantages:

  • It’s clear & declarative: themes themselves are defined in a single place separate from the implementation of theming machinery;
  • Explicit, fine-grained control over the resulting CSS: it’s you who decides how much markup will be generated and for which CSS properties; it means low size overhead when used properly.

Demo

Please go ahead and play with the demo below, and if something’s not clear after that, read on for the explanation.

Theming with SASS: Demo

Explanation

Let’s have a look at the usage from the developer’s perspective first, and then we will dissect the implementation.

Markup

Imagine we have an app rooted at #app-root :

Our example app markup

Now we’d like to style the app, and be able to easily switch between the themes. We do that by applying different theme classes to #app-root element, e.g.:

How to apply themes to the app

If you’re using a UI framework like React, it’s super-easy to apply themes to your entire component hierarchy by rendering your root component with different theme classes.

Defining Themes

To define themes, we’re declaring a SASS map which for each theme would map names of a styled CSS properties to their values for the given theme:

How to define themes

Two things to note here:

  • You can define any CSS properties in theme maps, not only colors;
  • In a real project, this is probably going to be a separate file, which you’ll import to the files with the actual elements’ styles.

Styling the Elements

The only thing that’s missing now is the actual styling of the app’s components. Consider this example:

How to style elements

So the idea here is that you wrap all themed properties in @themify mixin, and you access properties defined in themes by calling themed() function with the property name. Calling themed() outside @themify won’t work.

The Generated CSS

This is the CSS that the SASS code above compiles into:

The compiled CSS

As you can see, it’s very size-efficient: only the necessary markup was generated.

Implementation: Under the Hood

Let’s have a look now at what makes the above code tick. Fear not, it’s not that complicated!

Implementation of @themify and themed()

So the@themify mixin iterates over all themes (line 2) and outputs whatever was wrapped inside it with a .theme-#{themeName} class selector added before (lines 4–13, and compare SCSS and compiled CSS code above). Before outputting the wrapped content (line 11), it defines a global SASS map named $theme-map which contains values defined for the current theme (lines 5–9), so that the wrapped content can access them. After outputting the wrapped content (line 11), the map is set to null (line 12) so that it can’t be accessed from anywhere but the mixin content.

A helper function themed() is meant to be used inside the wrapped content and simplifies access to the $theme-map. Voilà, no magic!

Some Limitations

One limitation of this approach is that you can’t nest @themify mixins. But that’s fine since it’s a good idea to keep the themify-wrapped sections of code as short of possible to keep the resulting CSS as small as possible anyway.

Ending & Resources

That’s it! I hope it was useful for you and can help to theme your next app with ease.

And you — how do you approach theming in your projects? I’m curious to know! Please share your ways of theming in the comments.

At last, here’s some resources on the topic that you may find useful:

--

--

Dmitry Borody

Full-stack web deverloper. 🚀 Solving problems and building products with ⚛️ React, TypeScript, Node.js, Rust.