1

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:

1
  • You are aware that you can create local variables that scope just for the current file? Just have their name start with $_. Commented Oct 3, 2016 at 8:16

1 Answer 1

1

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 :)

Sign up to request clarification or add additional context in comments.

2 Comments

The mixin approach works, but the each directive throws an error (Error: Invalid CSS after ") {": expected "}", was ".{$body_class})
@rekam Good to hear that it helped :) I have updated my answer, there were a typo in Loop approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.