SASS/SCSS #each multiple arrays - css

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

Related

SCSS - How to loop nested maps within map-merge?

I have a nicely working SCSS function with which I can call any color like so:
color: clr(milk);
Now I would like to make some kind of loop within the map-merge so that when, for example I add a new nested map called 'tertiary' with some other colors, the colors automatically become available without having to add
map-get(colors, 'tertiary')
to the map-merge. Does anyone know how to do this? Below is my current function:
$colors: (
primary: (
milk: #fff,
cola: #000,
mine-shaft: #232323,
),
secondary: (
pampas: #f4f1ef,
pearl-brush: #e9e2dd,
alto: #ddd,
),
);
// Color generation
#function clr($color) {
$color: map-get(map-merge(map-get($colors, 'primary'), map-get($colors, 'secondary')), $color);
#return $color;
}
Nice project! map-merge() can be indeed used to achieve what you want, however it adds an unnecessary step. I'd recommend to simply use a nested loop coupled with an #if statement.
#function clr($find) {
#each $colorCategoryName, $colorCategory in $colors {
#each $colorName, $color in $colorCategory {
#if $find == $colorName {
#return $color;
}
}
}
}
For example: This...
$colors: (
"primary": (
"milk": #fff,
"cola": #000,
"mine-shaft": #232323,
),
"secondary": (
"pampas": #f4f1ef,
"pearl-brush": #e9e2dd,
"alto": #ddd,
),
);
#function clr($find) {
#each $colorCategoryName, $colorCategory in $colors {
#each $colorName, $color in $colorCategory {
#if $find == $colorName {
#return $color;
}
}
}
}
body {
color: clr(cola);
background-color: clr(pampas);
}
Will output:
body {
color: #000;
background-color: #f4f1ef;
}
Let me know if this isn't what you were looking for!

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);
}
}
}

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;
}
}

sass #each loop with multiple lists

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

Is it possible to take the variable's name in SASS?

I tried to make the following code look fancier with an #each or a #for loop (without any usable result).
.btn[data-btn-color="black"] {
#include colored-btn($black);
}
.btn[data-btn-color="blue"] {
#include colored-btn($blue);
}
.btn[data-btn-color="red"] {
#include colored-btn($red);
}
// ... and more colors ...
My current approach is to take value from the variable to use it as the value for the data-btn-color attribute and put that snippet into an #each loop.
Something like
#each $color in ($black, $blue) {
#include colored-btn($color);
}
which compiles into:
.btn[data-btn-color="black"] {
background-color: #000; // $black
}
.btn[data-btn-color="blue"] {
background-color: #00f; // $blue
}
Is there any function, which allows me to do such a thing?
You were so close! You don't want the () around what you want to go through in #each. I think Sass would just see what you have as one list item with a two item list inside.
Here is what I think you're trying to do:
$red: #f00;
$blue: #00f;
$black: #000;
$colors: red $red, blue $blue, black $black;
#mixin colored-button($background-color: #000){
background-color: $background-color;
}
#each $color in $colors {
$name: nth($color, 1);
$hex: nth($color, 2);
.btn[data-btn-color="#{$name}"]{
#include colored-button($hex);
}
}
Which would result in:
.btn[data-btn-color="red"] {
background-color: red; }
.btn[data-btn-color="blue"] {
background-color: blue; }
.btn[data-btn-color="black"] {
background-color: black; }

Resources