Improve mixin that outputs page-specific CSS As part of this answer, I created a mixin to generate some page-specific CSS for me.

I need to style an element based on a class I assign to the html-element. I do this for four different classes on the root-element, which gives me four similar CSS rules.

I'm looking for suggestions for the mixin itself. This is not limited to its function, also naming and the general idea may have so room for improvements.

Usage:


Pass the $element you want to style...
...and the $property (needs to hold a color value) you want to style i with
optionally, pass true as a third argument, if the light color variation should be used




@include themify(".page-title", background-color, true);


Example Output:

.page--blog .page-title {
    /* $blog-color-light */
    background-color: #6fbf00;
}

.page--portfolio .page-title {
    /* $portfolio-color-light */
    background-color: #ffaa10;
}

.page--profil .page-title {
    /* $profil-color-light */
    background-color: #6d91da;
}

.page--impressum .page-title {
    /* $impressum-color-light */
    background-color: #e04345;
}


Mixin:

@mixin themify($element, $property, $light-colors: false) {
    $pages: null;
    @if $light-colors == true {
        $pages: blog      $blog-color-light,
                portfolio $portfolio-color-light,
                profil    $profil-color-light,
                impressum $impressum-color-light;
    } @else {
        $pages: blog      $blog-color,
                portfolio $portfolio-color,
                profil    $profil-color,
                impressum $impressum-color;
    }

    @each $page in $pages {
        .page--#{nth($page, 1)} #{$element} {
            #{$property}: nth($page, 2);
        }
    }
}
This uses mappings, which are part of Sass 3.3. You can do the same thing without mappings, it's just not as pretty. In addition to allowing multiple selectors, it allows for more options than just light/dark colors (eg. background images, etc):

$themes:
    ( blog:
        ( default: red
        , light: lighten(red, 20%)
        )
    , portfolio:
        ( default: orange
        , light: lighten(orange, 20%)
        )
    , profile:
        ( default: green
        , light: lighten(green, 20%)
        )
    , impressum:
        ( default: blue
        , light: lighten(blue, 20%)
        )
    );

@mixin themify($property, $color: default) {
    @each $theme, $colors in $themes {
        .page--#{$theme} &amp; {
            #{$property}: map-get($colors, $color);
        }
    }
}

.foo, .bar {
    @include themify(background-color);
    @include themify(color, light);
}


Output:

/* line 27, ../sass/test.scss */
.page--blog .foo, .page--blog .bar {
  background-color: red;
}
/* line 27, ../sass/test.scss */
.page--portfolio .foo, .page--portfolio .bar {
  background-color: orange;
}
/* line 27, ../sass/test.scss */
.page--profile .foo, .page--profile .bar {
  background-color: green;
}
/* line 27, ../sass/test.scss */
.page--impressum .foo, .page--impressum .bar {
  background-color: blue;
}
/* line 27, ../sass/test.scss */
.page--blog .foo, .page--blog .bar {
  color: #ff6666;
}
/* line 27, ../sass/test.scss */
.page--portfolio .foo, .page--portfolio .bar {
  color: #ffc966;
}
/* line 27, ../sass/test.scss */
.page--profile .foo, .page--profile .bar {
  color: #00e600;
}
/* line 27, ../sass/test.scss */
.page--impressum .foo, .page--impressum .bar {
  color: #6666ff;
}


However, as you can tell from the output, it generates fairly inefficient CSS if you're using more than one property per selector.  You can deal with this by manipulating global variables (again, 3.3 syntax):

$colors: null; // private, don't touch

$themes:
    ( blog:
        ( base: red
        , light: lighten(red, 20%)
        )
    , portfolio:
        ( base: orange
        , light: lighten(orange, 20%)
        )
    , profile:
        ( base: green
        , light: lighten(green, 20%)
        )
    , impressum:
        ( base: blue
        , light: lighten(blue, 20%)
        )
    );

@mixin themify {
    @each $theme, $c in $themes {
        .page--#{$theme} {
            $colors: $c !global;

            @content;
        }
    }
}

@function theme($color: base) {
    @return map-get($colors, $color);
}

@include themify {
    .foo, .bar {
        background-color: theme(base);
        color: theme(light);
    }
}


Output:

/* line 42, ../sass/test.scss */
.page--blog .foo, .page--blog .bar {
  background-color: red;
  color: #ff6666;
}

/* line 42, ../sass/test.scss */
.page--portfolio .foo, .page--portfolio .bar {
  background-color: orange;
  color: #ffc966;
}

/* line 42, ../sass/test.scss */
.page--profile .foo, .page--profile .bar {
  background-color: green;
  color: #00e600;
}

/* line 42, ../sass/test.scss */
.page--impressum .foo, .page--impressum .bar {
  background-color: blue;
  color: #6666ff;
}