rekam rekam - 2 months ago 7
Sass (Sass) Question

Set a SASS variable depending

I'm searching a way to use a particular color depending on a class on the body tag.

I have a main scss file like this

// variables.scss
$bg-main: white;
$color-first: red;
$color-second: green;


And in my other files, I use the colors

// content.scss
.content {
.some-selector: {
// some styles
color: $color-second;
}
a:hover {
// some styles
color: $color-second;
}
}

// and same goes for menu.scss etc.


Now I have a dynamic class on the body, that changes depending on the current selected menu. I would like $color-second to be different for each body classes, and I don't know how to do that. The only solution I found was to move all the $color-second from each files into one single file, like this:

.body-1 {
.content a:hover, .content .some-selector {
color: green;
}
}
.body-2 {
.content a:hover, .content .some-selector {
color: blue;
}
}
.body-1 {
.content a:hover, .content .some-selector {
color: black;
}
}


So I don't need to write the color in each files. This works well, but if I need to set this $color-second to some other selector, I need to put that in this big file.

Is this possible to do this an other way?

I already checked these answers, but it didn't helped me much:


Answer

There are multiple ways to do this. The most obvious two which come to mind are mixins and loops:

Mixins

Just put everything you want into a single mixin, and then use it for every body class:

@mixin colored-content($color) {
  .content a:hover, .content .some-selector {
      color: $color;
  }

  /* Any other rules which use $color here */
}

.body-1 {
  @include colored-content(green);
}

.body-2 {
  @include colored-content('#FF0000');
}

.body-3 {
  @include colored-content(darken(red, 20));
}

You can extend this example with any number of arguments (for example, $textColor and $bgColor), conditions or rules.

With this approach you will not have SCSS code repetitions, and any updates will be introduced easily.

Loop

Another way is to use a simple loop:

$body_themes: (
    "body-1": green,
    "body-2": #FF0000,
    "body-3": darken(red, 2)
);

@each $body_class, $color in $body_themes {
  .{$body_class} {
    .content a:hover, .content .some-selector {
      color: $color;
    }

    /* Any other rules which use $color here */
  }
}

It is even shorter, but imho it is less readable.

P.S. It is possible to combine mixins and loops, by the way :)

Comments