Change a SCSS Variable based on CSS class

4.9k views Asked by At

I have a series of a tags that form a grid (each a is a block with the class .portfolio-grid-item).

Each .portfolio-grid-item contains several div and heading elements and uses a default color via a variable ($grid-color: $blue;).

I am trying to create a SCSS rule that will do the following:

  • Check if an additional class is assigned to the a tag.
  • If there is an additional class, replace the default color variable with a new one.
  • If not, fallback to the default.

e.g.

An element classed as .portfolio-grid-item .orange should, replace $grid-color: $blue with $grid-color: $orange;

I have tried using an mixin with an if statement, but I have never done this before and I am not sure if the method is correct, or supported.

My Pen is here: http://codepen.io/anon/pen/EjwarE

Any advice would be really appreciated!

UPDATE:

To put this in some simple terms (I know this isn't true code, it's just the logic I am aiming for, hopefully this helps!):

// Default
$grid-color: $blue


// Statement
if HTML element has class = `.orange`

// Change the following variable
$grid-color: $orange

The idea being that this will override all instances of $grid-color in one shot

2

There are 2 answers

3
Gerico On BEST ANSWER

This my be more along the lines of what you need. I'm sure it can be improved but I've used a map of colour values which I loop through to produce your colour variants.

I didn't use an if statement purely because by default I modified your main element CSS to contain the blue background as standard. In this way our loop only needs to churn out the additionally colours that are mapped and the styles are overridden via the extra class you add to that element.

SCSS:

//set your base colours
$colors: (
  green: green,
  blue: blue,
  orange: orange
);

//loop through your map and apply colours to the mapped values. This overrides the default where the additional class is applied. 
@each $colors, $specific in $colors {
  .portfolio-grid-item.#{$colors} {
    background: $specific;
  }
}

Your portfolio item:

// Gird Sizings
.portfolio-grid-item {
  height: $grid-item-height;   
  position: relative;
  text-decoration: none;
  float: left;
  width: 33.33%;
  //set default
  background: $grid-color;
}

Working example - Codepen

Using this method you could apply colours to the font etc by adapting the map to contain more values. For instance you could map both background AND font colour in the map. Such as:

//set your base colours
$colors: 
  (green, white, green),
  (orange, white, orange);

//loop through your map and apply colours to the mapped values. This overrides the default where the additional class is applied. 
@each $color, $text, $bg in $colors {
  .portfolio-grid-item.#{$color} {
    background: $bg;
    color: $text;
  }
}

You can then add hover to the loop and darken the background mapped to $bg by whatever you need. From what I understand this should achieved the desired result.

4
Razvan B. On

Well, you can do something like this:

@mixin gridbg($bg) {
   @if $bg == blue {
   background: $blue;
 } @else if $bg == green {
   background: $green;
 } @else if $bg == orange {
   background: $orange;
 }
}

.orange {
  @include gridbg(orange);
}

.green {
  @include gridbg(green);
}

.blue {
  @include gridbg(blue);
}

Update

The above was just a simple example, but you can do much more with mixins: Here is a preview:

.orange {
    @include gridbg(orange);
    h3 {
      color: $grid-color
    }
    h5 {
      color: white;
      background: $orange;
    }
    &:hover {
        @include gridbghover(orange);
        h3 {
          color: $grid-color
        }
        h5 {
          color: white;
          background: darken($orange, 20%);
        }
    }
}

And a demo