Theming a web application typically involves swapping out stylesheets or moving CSS classes around. But what if you have a single page application? It’s a little tricky, but EmberJS and SASS make it incredibly easy.
There are two primary goals that I wanted to achieve:
Swap Themes Quickly
Rather than have code change colors, fonts, etc. on the fly, it makes a lot more sense to already have those styles pre-defined in CSS.
When exposed as an Ember Addon, our implementation should allow for 3rd parties to add their own themes easily.
How It Works
This implementation assumes a few things:
The bulk of the theme-switching work is done by a theme service and some SASS mixins.
Let’s Get SASSy
Let’s first look at the SASS code. There’s a $themes map declared. It’s written so that there are base themes and themes within the base. For example, suppose you had different areas of your application to theme, but they should still be a part of your overall theme (like a namespace):
In this example, foo is the base theme and primary and secondary are the sub-themes.
The properties of the map are arbitrary, but they are what you’ll refer to later on in CSS, sort of like a theme API. Think of it like “for this div.class-name, use the primary color for the background”.
Note: We will be using a data-theme attribute on HTML tags. I thought this was cleaner than swapping class attributes and the intent is clear in the markup.
Here is a gist of the SASS functionality to make theme switching happen. I’ll come back to using it momentarily.
Now let’s take a look at the theme service. Anything that’s going to consume this service will be able to:
- bind to the current theme
- set the base theme
- set the sub-theme
Theming Your Application
How you determine when themes change is up to you. But here’s an example of swapping themes at a route:
Determining what you want to theme is also up to you. Let’s assume you have a component, here’s an example of using the theme service:
Two things to note:
- Your component injects the theme service
- Your template has a div with a data-theme attribute that is bound to the theme.name.
As the theme.name property changes, your data-theme will as well.
Last, to wire this all together, you have to style your div with the theme property you want. For example:
Only the first couple lines are relevant, the remainder displays what the resulting CSS will look like.
In the SASS code, it merges a property $theme-additional if it exists into the $themes map. If this code were available as an addon, you could add your own themes as follows:
- Create your own theme map, so long as it is named $theme-additional.
- Make sure you @import it prior to $themes.
If you thought this was interesting, found a way to make it better or wound up doing something awesome with it, I’d love to hear about it.
Here’s an example of theme switching in action:
Originally published at jonpitcherella.com on April 2, 2016.