ronaldpoi
ronaldpoi

Reputation: 201

SASS loop to simplify repetitive code

I have this set of repetitive classes (variables names and overall code simplified for demonstration purposes):

&-category01 { background: linear-gradient((nth($colors-category01, 1), nth($colors-category01, 2)); }
&-category02 { background: linear-gradient((nth($colors-category02, 1), nth($colors-category02, 2)); }
&-category03 { background: linear-gradient((nth($colors-category03, 1), nth($colors-category03, 2)); }
&-category04 { background: linear-gradient((nth($colors-category04, 1), nth($colors-category04, 2)); }

The $colors-... bit comes from a map:

$colors-category01: (#ab1b99, #8f017d);
$colors-category02 (#d2544b, #87352f);

How can I simplify this code with a SASS loop?

Remember that variable interpolation is not valid inside a loop or mixin. Also, my real code is more complex than this practical situation.

My goal is to get this as output:

.category01 { linear-gradient(#ab1b99, #8f017d); }
.category02 { linear-gradient(#d2544b, #87352f); }
(etc...)

Upvotes: 1

Views: 739

Answers (1)

cjl750
cjl750

Reputation: 4629

If all your color category variables have the same number of colors in them, you can create a new variable that is just a list of all the variables with actual values in them and then loop through that new variable with an @each function.

See @each loop with index for more on that.

$colors-category01: (#ab1b99, #8f017d);
$colors-category02: (#d2544b, #87352f);
$colors-category03: (#ffffff, #000000);
$colors-category04: (#f0f0f0, #333333);

$color-categories: $colors-category01, $colors-category02, $colors-category03, $colors-category04;


@each $category in $color-categories {
  $i: index($color-categories, $category);

  .category0#{$i} {
    background-image: linear-gradient(nth($category, 1), nth($category, 2));
  }
}

Results in:

.category01 {
  background-image: linear-gradient(#ab1b99, #8f017d);
}
.category02 {
  background-image: linear-gradient(#d2544b, #87352f);
}
.category03 {
  background-image: linear-gradient(#ffffff, #000000);
}
.category04 {
  background-image: linear-gradient(#f0f0f0, #333333);
}

Unfortunately if the reality is that your different color categories actually have different numbers of colors in them, then things get a lot more complicated. I can't personally figure out a way you could loop through an indefinite number of values in those maps and chain together the background-image value. (Which is not to say for sure that it can't be done, but it may well end up taking you longer to figure out than the time you'd be saving by using a loop.)

But you could possibly do a bunch of @if statements to cover a reasonable number of possibilities, if you really wanted to.

$colors-category01: (#ab1b99, #8f017d);
$colors-category02: (#d2544b, #87352f);
$colors-category03: (#ffffff, #000000, #2d2d77);
$colors-category04: (#f0f0f0, #333333, #00ff5e, #ffa900);

$color-categories: $colors-category01, $colors-category02, $colors-category03, $colors-category04;

@each $category in $color-categories {
  $i: index($color-categories, $category);

  .category0#{$i} {
        @if length($category) == 2 {
            background-image: linear-gradient(nth($category, 1), nth($category, 2));
        }
        @if length($category) == 3 {
            background-image: linear-gradient(nth($category, 1), nth($category, 2), nth($category, 3));
        }
        @if length($category) == 4 {
            background-image: linear-gradient(nth($category, 1), nth($category, 2), nth($category, 3), nth($category, 4));
        }

        //et cetera
  }
}

Outputs:

.category01 {
  background-image: linear-gradient(#ab1b99, #8f017d);
}
.category02 {
  background-image: linear-gradient(#d2544b, #87352f);
}
.category03 {
  background-image: linear-gradient(#ffffff, #000000, #2d2d77);
}
.category04 {
  background-image: linear-gradient(#f0f0f0, #333333, #00ff5e, #ffa900);
}

Upvotes: 2

Related Questions