Dealing with Color Schemes in Sass

Tweet

A lot of sites have a specific color scheme for every section. Even this very site you are reading does this – you are in the blue section AKA CSS. This is a clever design trend to create clear distinctions between various parts of the same entity.

But on the technical side, this can be a pain to work with. Not because it is overly complicated – more because it involves a lot of annoying repetition.

Unless, that is, you automate the process with — let’s say — Sass. Then you have something really easy to work with. Since I have had to do this more than once, I’ll show you how I handle the situation.

How Do Color Schemes Work?

Before getting to the code, we should ask how does color scheming in CSS actually work? Well, if you don’t plan on using any JavaScript (which sounds like a good idea to me) probably the easiest way is setting up a theme class in your HTML and CSS, so that every element that needs to be styled according to the theme becomes a child of this class.

SitePoint follows this method. If you look at the main wrapper that has an ID of #primary, you’ll see it also has a class of .category-css. This makes the theme styling easy.

Note: you can read how I deal with themes and layouts with Twig in this article from my own blog.

Once you have the class set up on your wrapper, it is very easy to make your styles conditional. Let’s say you have an element with a class of .element that needs to be styled according to the theme:

.theme-banana .element {
  color: yellow;
}

.theme-blueberry .element {
  color: purple;
}

.theme-cherry .element {
  color: red;
}

I used the color property but it could just as well be background, border-color or even box-shadow. Whatever! Even a background position for a sprite or an image path if that’s needed.

It works like a charm but, as you can see, it requires us to type the same thing 3 times in a row. And if we need to add another theme, we have to repeat it yet again. Then if we need to make other stuff conditional to the theme, we need to repeat these kind of rules again and again… There has to be an easier way!

Sass to the Rescue

Wouldn’t it be cool if we could just give the name of the theme and the color to some kind of function so it immediately dumps everything we need? Well that does sound like the perfect use case for a mixin, doesn’t it?

Here’s a simple mixin that we only need to write once:

@mixin theme($name, $color) {
  .#{$name} {
    .element {
      color: $color;
    }
  }
}

And here is how you would use it:

@include theme(theme-banana, yellow);
@include theme(theme-blueberry, purple);
@include theme(theme-cherry, red);

Abracadabra! And here is what the CSS will look like when it’s compiled (View code here):

.theme-banana .element {
  color: yellow;
}

.theme-blueberry .element {
  color: purple;
}

.theme-cherry .element {
  color: red;
}

Well, that looks neat, doesn’t it? With nothing more than a small mixin and an include per theme, we managed to have all our CSS dumped in like magic. So whenever we need to make something themed, we simply have to update the mixin core to add whatever is needed.

Let’s say we want .other-element to have a themed background color (View code here):

@mixin theme($name, $color) {
  .#{$name} {
    .element {
      color: $color;
    }
    
    .other-element {
      background: $color;
    }
  }
}

It’s that simple! As you can see, Sass makes color scheming much easier.

Multiple Colors per Theme

Depending on the feel you want to give to your site, you might like to have several colors in a single theme. In such a case, you have two options:

I’d advise using the second option as much as you can because it’s much easier than asking for a second color. That being said, sometimes (often?) designers want to have specific colors that arent’ easy to produce using color functions.

In case you want to try the second option, here is what your mixin might look like (View code here):

@mixin theme($name, $color) {
  $primary: $color;
  $secondary: lighten(adjust-hue($color, 20), 10%);

  .#{$name} {
    .element {
      color: $primary;
    }

    .other-element {
      background: $secondary;
    }
  }
}

Automating the Mixin Inclusions

You may have noticed we still have some code repetition when we include the mixin for each theme. We have to repeat @include theme(/* ... */), and that kind of sucks. It’s not very DRY.

What if we had some kind of configuration object that we can use to generate all the themes dynamically? That sounds like the perfect usecase for a map (available in Sass 3.3):

$themes: (
  theme-banana: yellow,
  theme-blueberry: purple,
  theme-cherry: red
) !default;

Note: if you need more than one argument, feel free to use a list as a value (e.g. (banana: yellow orange)); it is supported.

Now that we have our map set up, we can loop through it and include the theme from within the loop.

@each $theme, $color in $themes {
  @include theme($theme, $color);
}

(View code)

That being said, there will most likely be only one theme used per page so it might be overkill to include all themes each time. At my company, we include only the theme we need for the current page; hence, minimal CSS output. However this is dependent on your own deploy process, which would be beyond the scope of this article.

Note: if you’re using Sass 3.2, you could use nested lists instead of a map. That works exactly the same.

Final Words

As you can see, making a theme-based site is not only easy to set up but also quite elegant, since you can have your theme configuration in a completely different place (or file) from where the themes are being called.

For instance, you could have your configuration map in a config file (_config.scss) and your theme instantiations in a theme file (_themes.scss). Pretty convenient.

Let us know in the comments if if you have any of your own suggestions for using Sass when working with CSS color schemes. And just for fun, below you’ll find a CodePen demo that incorporates these ideas into a theme switcher that’s triggered by JavaScript.

See the Pen Sass Color Schemes Demo by SitePoint (@SitePoint) on CodePen.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://ahmadalharbi.com/ Ahmad Alharbi

    That was immensely helpful, Thanks a lot!

  • http://hugogiraudel.com/ Hugo Giraudel

    You cannot have dynamic variables in Sass. To make things work, build a two dimensional list (or a Sass 3.3 map) with the name of the color for the class as first item (or key), and the color as second item (or value).

    Something like this (with a 2 dimensional list):
    $color-map: (
    yellow rgb(255, 241, 0),
    orange rgb(255, 140, 0)
    )

    Then you loop over the map like this:
    @each $item in $color-map {
    $name: nth($item, 1);
    $color: nth($item, 2);

    .my-#{$name} {
    background-color: $color;
    }
    }

  • http://hugogiraudel.com/ Hugo Giraudel

    I think SassyJSON could be an idea. Basically, you make your back-office write a JSON file, which you import and decode in your Sass with SassyJSON. Would be neat in my opinion. :)

    • https://www.twitter.com/mh_nichts mh_nichts

      oh, thank you, I will have a look at SassyJSON !