Sass @each with multiple variables
Asked Answered
N

5

24

I'm just getting started with Sass and Compass, and I'm loving it. Something I'd like to do is take advantage of the @each function to simplify repetitive tasks. However, I've only seen examples of @each inserting one variable, and I'd like to be able to use multiple variables.

The standard way (from the Sass Reference):

@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}

Which is great, but I'd like to be able to do something like:

@each {$animal $color} in {puma black}, {sea-slug green}, {egret brown}, {salamander red} {
  .#{$animal}-icon {
    background-color: #{$color};
  }
}

Is this possible?

Necker answered 4/7, 2011 at 14:8 Comment(0)
G
30

I'm in the same boat (beginner to Sass/Compass) and had to do something similar. Here's what I came up with, using nested lists:

$flash_types: (success #d4ffd4) (error #ffd5d1);

@each $flash_def in $flash_types {
    $type: nth($flash_def, 1);
    $colour: nth($flash_def, 2);

    &.#{$type} {
        background-color: $colour;
        background-image: url(../images/#{$type}.png);
    }
}

It's not the most elegant solution but it should work if you can't find anything else. Hope it helps! I'd appreciate a better method too :)

Gujranwala answered 4/7, 2011 at 20:14 Comment(1)
For reference: if you need to combine two lists together to create a list of pairs, like $flash_types, you can use Sass function zip.Guayaquil
C
51

Just came across this, have the answer for you. In Sass, you can actually have a multidimensional list, so instead of constructing individual variables, you'd create one variable to hold them all, then loop over them:

$zoo: puma black, sea-slug green, egret brown, salamander red;

@each $animal in $zoo {
  .#{nth($animal, 1)}-icon {
    background-color: nth($animal, 2);
  }
}

You can have multidimensional lists just like you would have single dimensional lists as long as each nested dimension is separated in a different manner (in our case, commas and spaces).

UPDATE Oct 24, 2013

In Sass 3.3, there is a new data type called maps which are a hashed set of items. With this, we can rewrite my previous answer in the following way to much more closely resemble the desired result:

$zoo: ("puma": black, "sea-slug": green, "egret": brown, "salamander": red);

@each $animal, $color in $zoo {
    .#{$animal}-icon {
        background-color: $color;
    }
}

You can see this in action over at SassMeister

Costrel answered 5/12, 2011 at 1:39 Comment(1)
This is essentially the same as treeki's answer, but yours is much more elegant.Analytic
G
30

I'm in the same boat (beginner to Sass/Compass) and had to do something similar. Here's what I came up with, using nested lists:

$flash_types: (success #d4ffd4) (error #ffd5d1);

@each $flash_def in $flash_types {
    $type: nth($flash_def, 1);
    $colour: nth($flash_def, 2);

    &.#{$type} {
        background-color: $colour;
        background-image: url(../images/#{$type}.png);
    }
}

It's not the most elegant solution but it should work if you can't find anything else. Hope it helps! I'd appreciate a better method too :)

Gujranwala answered 4/7, 2011 at 20:14 Comment(1)
For reference: if you need to combine two lists together to create a list of pairs, like $flash_types, you can use Sass function zip.Guayaquil
S
2

Another way I used if anyone needs it:

$i:0;
@each $name in facebook, twitter, google_plus, instagram, youtube, pinterest {
    $i:$i+1;
}
Suppositious answered 12/7, 2013 at 3:50 Comment(0)
E
1

This functionality is supported for Sass 3.3.0 and above (I just updated from 3.2.14 to 3.4.4 in order to use it).

@each $animal, $color in (puma, black), (sea-slug, green), (egret, brown), (salamander, red) {
  .#{$animal}-icon {
    background-color: $color;
  }
}

I'd recommend to check the changelog for backwards incompatibilities, if you're updating Sass.

Sass reference for multiple assignments with @each

Eddington answered 19/9, 2014 at 18:5 Comment(0)
F
1

Another solution could be to create different lists and "zip" them.

//Create lists
$animals: puma, sea-slug, egret, salamander;
$animals-color: black, green, brown, red;

//Zip lists
$zoo: zip($animals, $animals-color);

//Do cycle
@each $animal, $color in $zoo {
    .#{$animal}-icon {
        background-color: $color;
    }
}

Probably this solution is more complicated to mantain than the others, but if you use a list more than one time, you can save time. (was my case)

Friedrich answered 29/3, 2016 at 11:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.