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
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
- 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
data-themeattribute that is bound to 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
- Make sure you
@importit prior to
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:
You can view the full gist here.