Using Sass lists and each loops for super easy CSS branding

Lately, here at Mikamai we’ve been working on a large client project that substantially consists in building an API for injecting content in a page. The content is requested via a JS API that accepts some arguments, one of which being the brand the developer needs – based on this brand, the script injects different content that needs to be styled in different ways (one per brand). So, how to approach that last step?

The problem

The first solution that came to mind was to assign a different class to the body and, based on that, apply the according styles for each different brand. For example:

  body {
    /* Default style */
    background-color: #ffffff;

    &.brand-one {
      background-color: #c09853;

      .title {
        color: #fcf8e3;
      }
    }

    &.brand-two {
      background-color: #eaeaea;

      .title {
        color: #a200b8;
      }
    }

    /* And so on.. */
  }

This could work, but we’ll eventually have some problems. The first (and probably biggest) one is that we have a lot of duplicated code, that means an hard-to-mantain codebase and readability concerns.

Sass to the rescue

Among Sass’ awesome features, there are two in particular that could come handy in our case: Lists (arrays, basically) and each loops (I’ll let you guess that). With these tools in our hands, we could convert the above code snippet in something like this:

$brands:  (brand-one   #c09853 #fcf8e3), 
          (brand-two   #eaeaea #a200b8),
          (brand-three #000000 #222222);

body {
  @each $brand in $brands {
    $division: nth($brand, 1);
    $division-bg-color: nth($brand, 2);
    $division-title-color: nth($brand, 3);

    &.#{$division} {
      background-color: #{$division-bg-color};

      .title {
        color: #{$division-title-color};
      }
    }
  }
}

What we’re doing here is creating some nested Sass lists with 3 values: respectively the brand name, the brand background color and the brand title color. It could be expressed this way:

$list: (brand-name background-color title-color)

Then, in the body style declaration, we start a @each loop that iterates over each list value and - with the nth operation - assigns every nested value to a variable. We then interpolate our newly created variables in our style declaration, resulting in what we wanted at the beginning. Cool, right? But we could improve that solution to be more flexible and clean. How?

Mixins and variables

The power of Sass offers again great ways to write modular and easy to read and mantain code. Defining a mixin that includes our über-cool function is super easy:

$brands:  (brand-one $brandone-bgcolor $brandone-title-color), 
          (brand-two $brandtwo-bgcolor $brandtwo-title-color),
          (brand-three $brandthree-bgcolor $brandthree-title-color);

@mixin brand-colors {
  @each $brand in $brands {
    $division: nth($brand, 1);
    $division-color: nth($brand, 2);
    $division-title-color: nth($brand, 3);

    &.#{$division} {
      background-color: #{$division-color};

      .title {
        color: #{$division-title-color};
      }
    }
  }
}

As you can see we just defined a mixin (presumably in a separated helper.scss file) that we can trivially include in our main css. Plus, we don’t have any hardcoded color value in our mixin, since we replaced them with variables (that we could declare in a specific var.scss file – separation of concerns, right?). That means that in the end we’ll have 3 files:

  • vars.scss
  • helpers.scss
  • main.scss

In vars.scss we’ll have something like that:

  $brandone-bgcolor: #eaeaea;
  $brandone-title-color: #333333;

  // etc.

In helpers.scss our “brand-colors” mixin:

$brands:  (brand-one $brandone-bgcolor $brandone-title-color), 
          (brand-two $brandtwo-bgcolor $brandtwo-title-color),
          (brand-three $brandthree-bgcolor $brandthree-title-color);

@mixin brand-colors {
  @each $brand in $brands {
    $division: nth($brand, 1);
    $division-color: nth($brand, 2);
    $division-title-color: nth($brand, 3);

    &.#{$division} {
      background-color: #{$division-color};

      .title {
        color: #{$division-title-color};
      }
    }
  }
}

In main.scss we could do something like that:

  @import "vars";
  @import "helpers";

  body {
    @include brand-colors;
  }

Ta-dah! Modular, extensible code and easy to mantain styles for all the brand variations you wish.

Lists and mixins can do much more than this. Try them and you’ll never come back! 

Bonus codepen bonanza.

Notes

  1. mikamayhem posted this