sass #each loop with multiple lists - css

developing in scss
I have the two variable lists:
$ids: 21, 33, 73;
$colors: #fff, #000, #333;
and the following #each loop.
#each $id, $color in ($ids, $colors) {
.category--#{$id},
.post--#{$id} {
color: #{$color};
}
}
I want to display the following
.category--21,
.post--21 {
color: #fff
}
.category--33,
.post--33 {
color: #000
}
.category--73,
.post--73 {
color: #333
}
But I'm getting this instead
.category--21,
.post--21 {
color: 33;
}
.category--#fff,
.post--#fff {
color: #000;
}
Unsure of my structure. Obviously I have much longer variables lists (just added 3 to each one for demo purposes).
Any constructive feedback welcome. Thanks

Based on my understanding, I think #each is not the correct option for you as you don't have the key and value pair as one item. Below is what the documentation says about #each: (emphasis is mine)
The #each directive can also use multiple variables, as in #each $var1, $var2, ... in <list>. If <list> is a list of lists, each element of the sub-lists is assigned to the respective variable.
As you can see from the above statement, in your case the $ids would be treated as one list and the $colors would be treated as another. It means that
1st iteration $id is 21, $color is 33 and 73 not assigned
2nd iteration $id is #fff, $color is #000 and #333 is not assigned.
It might be better for you to use the #for loop like in the below snippet:
$ids: 21, 33, 73;
$colors: #fff, #000, #333;
#for $i from 1 through length($ids) {
$id: nth($ids, $i);
$color: nth($colors, $i);
.category--#{$id},
.post--#{$id} {
color: #{$color};
}
}

Hi you misuse it :D #each is iterate list by list see below
$pair: (21, #fff), (33, #000), (73, #333);
#each $id, $color in $pair {
.category-#{$id},
.post-#{$id} {
color: #{$color};
height: 20px;
}
}
doc reference: http://sass-lang.com/documentation/file.SASS_REFERENCE.html#each-multi-assign

Related

scss interpolation help for passing the values

I need to create dynamic classes for which I am creating a scss code to create the classes for all the possible values. Below is my code:-
$colors: (
"black": "0,0,0",
"white": "255,255,255",
"red" : "255,0,0"
);
$opacity:9;
#for $i from 0 through $opacity {
$j:$i/10;
#each $color, $rgb in $colors {
$rgba: "#{$rgb},#{$j}";
.background-#{$color}-#{$i} {
background: #{$rgba};
}
}
}
I want it to give out put as :-
.background-black-0 {
background: rgba(0,0,0,0);
}
.background-white-0 {
background: rgba(255,255,255,0);
}
.background-red-0 {
background: rgba(255,0,0,0);
}
.background-black-1 {
background: rgba(0,0,0,0.1);
}
.background-white-1 {
background: rgba(255,255,255,0.1);
}
.background-red-1 {
background: rgba(255,0,0,0.1);
}
struggling with the interpolation for rgba(). Otherwise its getting the exact values I want. If you check my code in https://www.sassmeister.com/ you will see it.
You could use directly your colors as rgb color in your map and then add opacity in your #for loop:
$colors: (
"black": rgb(0,0,0),
"white": rgb(255,255,255),
"red": rgb(255,0,0)
);
$opacity:9;
#for $i from 0 through $opacity {
$j:$i/10;
#each $color, $rgb in $colors {
.background-#{$color}-#{$i} {
background: rgba($rgb, $j);
}
}
}

SASS/SCSS #each multiple arrays

I am trying to write a sass mixing using the values from two arrays to output my button classes. Not sure if what I am trying to do is possible at all.
So I have two arrays:
$buttonNames: ('black', 'primary', 'red', 'green', 'orange');
$buttonColors:(black, blue, red, green, orange);
and then my mixin is:
#mixin underlineButton($class, $name, $size, $color: black) {
.#{$class}-underline-#{$name} {
background-color: transparent;
border-bottom: $size + px solid $color;
border-radius: 0;
font-size: .75rem;
}
}
and then I do an #each loop for the names, and attempted to nest another loop inside this to get the colors. Obviously this isn't working! Just wondering if it is even possible.
#each $name in $buttonNames {
#each $color in $buttonColors {
#include underlineButton('btn', $name, 3, $color)
}
}
The desired output would be something like:
.btn-underline-black {
background-color: transparent;
border-bottom: 3px solid black;
border-radius: 0;
font-size: .75rem;
}
// .btn-underline-* for the rest of the matching keys and colors
Here's a DEMO
If you need to keep your values separate, in 2 lists, then you can...
// loop over $buttonNames
#each $buttonName in $buttonNames {
// Find the current index of $buttonNames...
$index: index($buttonNames, $buttonName);
// ... to pull the right from $buttonColors
#include underlineButton('btn', $buttonName, 3, nth($buttonColors, $index));
}
However, using a map is a little easier.
$buttons: (
'black': black,
'primary': blue,
'red': red,
'green': green
);
#each $buttonName, $color in $buttons {
#include underlineButton('btn', $buttonName, 3, $color)
}
$buttons: ('black', $black),
('primary', $primary),
('red', $red),
('green', $green);
#each $buttonName, $color in $buttons {
#include underlineButton('btn', $buttonName, 3, $color)
}

Using SCSS variable inside a variable

I want to use a SCSS loop as below:
#each $var in dark, purple, green, cyan, silver, white {
.text-#{$var} {
color: nth($color-, $var);
}
.btn-#{$var} {
background-color: nth($color-, $var);
}
}
in order to use the following variables:
$color-dark: #0D0E1E;
$color-purple: #333366;
$color-green: #33cc99;
$color-cyan: #00cccc;
$color-silver: #ccc;
$color-white: #fff;
but it is not working.
$color-#{$var} was not working as well. Can I do this?
nth gets an item in a list. The first argument is the list, the 2nd is an index in the list. Also SASS thinks anything with a $ is a variable, so $color- is a variable. You haven't defined $color- as a variable, and that's not your intended use.
DOCS.
But you can get your desired result with a map...
DEMO
$color-dark: #0D0E1E;
$color-purple: #333366;
$color-green: #33cc99;
$color-cyan: #00cccc;
$color-silver: #ccc;
$color-white: #fff;
$colors: (
dark: $color-dark,
purple: $color-purple,
green: $color-green,
cyan: $color-cyan,
silver: $color-silver,
white: $color-white
);
#each $name, $val in $colors {
.text-#{$name} {
color: $val;
}
.btn-#{$name} {
background-color: $val;
}
}

Using model attributes for the page style on Rails [duplicate]

I have a list in SASS, and I'm trying to access on of the items by using bracket notation:
$collection[1];
but that gives me an error.
Is there any other way to do this?
Why do I want to do this?
I have a list of colors that have to be set on different elements according to a colors assigned to them by the server. The markup has numbered classes (color-0, color-1, etc.). Here's the CSS I'm aiming for:
.color-0 { color: red }
.color-1 { color: orange }
.color-2 { color: green }
.color-3 { color: blue }
/* many more, with more complex colors... */
Instead of writing it all by hand, I figured I could use a SASS collection with a loop:
$color-collection: ('red', 'orange', 'green', 'blue');
$color-count: length($color-collection);
#for $i from 0 to $color-count {
.color-#{$i} {
color: $color-collection[ $i ];
}
}
but this just gives me the following error:
Syntax error: Invalid CSS after "...color-collection": expected ";", was "[ $i ];"
How can I accomplish this?
$color-collection: ('red', 'orange', 'green', 'blue');
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: unquote(nth($color-collection, $i+1));
}
}
Use nth(), also unquote() if you want to pass quoted strings.
Though, I personally wouldn't:
$color-collection: (red, rgba(50,50,80, .5), darken(green, 50%), rgba(blue, .5));
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: nth($color-collection, $i+1);
}
}
Because then you can pass any color object.
You can use #each rule instead of #for, which is more semantic, faster, and it makes the code shorter:
$color-collection: (red, orange, green, blue);
#each $color in $color-collection {
.color-#{$color} {
color: $color;
}
}
Or if you prefer you can use $color-collection list directly into the #each directive:
#each $color in red, orange, green, blue {
.color-#{$color} {
color: $color;
}
}
As #bookcasey says is preferable to use unquoted strings because then you can pass any color object or function
Sass reference for #each directive
just came across this and tested bookcasey's answer, which works well but I wanted to use the color name as the class instead; I found that this code works as I needed.
$colors: ( 'black', 'white', 'red', 'green', 'blue' );
#for $i from 0 to length($colors) {
$thisColor: unquote(nth($colors, $i+1));
.color-#{$thisColor} {
color: $thisColor;
}
}
using the #{...} allows you to use functions as well, so if you need to use an arbitrary name that may not be used directly in the rules you could use
#for $i from 0 to length($colors) {
.color-#{unquote(nth($colors, $i+1))} {
// some rules that don't actually use the var
// so there's no need to cache the var
}
}
output:
.color-black { color: black; }
.color-white { color: white; }
.color-red { color: red; }
// etc..
Hope this helps someone else!
I had similar problem and tried Alex Guerrero solution. Didn't work form me cause output was like .color-gray:{gray}; instead of .color-1:{gray};.So I modified it a bit and it looks like this:
$color-pallete: (gray, white, red, purple)
$i: 0
#each $color in $color-pallete
.color-#{$i}
color: $color
$i: $i + 1
Oh, ye. I use SASS, not SCSS.

Accessing an array key in SASS

I have a list in SASS, and I'm trying to access on of the items by using bracket notation:
$collection[1];
but that gives me an error.
Is there any other way to do this?
Why do I want to do this?
I have a list of colors that have to be set on different elements according to a colors assigned to them by the server. The markup has numbered classes (color-0, color-1, etc.). Here's the CSS I'm aiming for:
.color-0 { color: red }
.color-1 { color: orange }
.color-2 { color: green }
.color-3 { color: blue }
/* many more, with more complex colors... */
Instead of writing it all by hand, I figured I could use a SASS collection with a loop:
$color-collection: ('red', 'orange', 'green', 'blue');
$color-count: length($color-collection);
#for $i from 0 to $color-count {
.color-#{$i} {
color: $color-collection[ $i ];
}
}
but this just gives me the following error:
Syntax error: Invalid CSS after "...color-collection": expected ";", was "[ $i ];"
How can I accomplish this?
$color-collection: ('red', 'orange', 'green', 'blue');
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: unquote(nth($color-collection, $i+1));
}
}
Use nth(), also unquote() if you want to pass quoted strings.
Though, I personally wouldn't:
$color-collection: (red, rgba(50,50,80, .5), darken(green, 50%), rgba(blue, .5));
#for $i from 0 to length($color-collection) {
.color-#{$i} {
color: nth($color-collection, $i+1);
}
}
Because then you can pass any color object.
You can use #each rule instead of #for, which is more semantic, faster, and it makes the code shorter:
$color-collection: (red, orange, green, blue);
#each $color in $color-collection {
.color-#{$color} {
color: $color;
}
}
Or if you prefer you can use $color-collection list directly into the #each directive:
#each $color in red, orange, green, blue {
.color-#{$color} {
color: $color;
}
}
As #bookcasey says is preferable to use unquoted strings because then you can pass any color object or function
Sass reference for #each directive
just came across this and tested bookcasey's answer, which works well but I wanted to use the color name as the class instead; I found that this code works as I needed.
$colors: ( 'black', 'white', 'red', 'green', 'blue' );
#for $i from 0 to length($colors) {
$thisColor: unquote(nth($colors, $i+1));
.color-#{$thisColor} {
color: $thisColor;
}
}
using the #{...} allows you to use functions as well, so if you need to use an arbitrary name that may not be used directly in the rules you could use
#for $i from 0 to length($colors) {
.color-#{unquote(nth($colors, $i+1))} {
// some rules that don't actually use the var
// so there's no need to cache the var
}
}
output:
.color-black { color: black; }
.color-white { color: white; }
.color-red { color: red; }
// etc..
Hope this helps someone else!
I had similar problem and tried Alex Guerrero solution. Didn't work form me cause output was like .color-gray:{gray}; instead of .color-1:{gray};.So I modified it a bit and it looks like this:
$color-pallete: (gray, white, red, purple)
$i: 0
#each $color in $color-pallete
.color-#{$i}
color: $color
$i: $i + 1
Oh, ye. I use SASS, not SCSS.

Resources