Assign multiple values from variable in SCSS - sass

I've variable named classes where each key has style values
$classes : (
class1: (
font-size: 15px,
color: blue
),
class2: (
font-size: 20px,
font-weight: 600,
background-color: red
)
)
I'm writing #each rule in scss like below.
#each $key, $value in $classes {
.#{$label} {
// How to assign values here
}
}
I'm able to get class name but unable to add all values here. Any idea how to do it.

I found the solution of above problem.
We can't assign key - value pair directly in scss.
Here we need to apply #each loop till the end
#each $key, $value in $classes {
.#{$label} {
#each $key1, $value1 in $value {
.#{$key1}: $value1
}
}
}

Related

Count up with #each from a list with Sass

I’m wondering if I can add a ‘counter’ with Sass when using the #each function. I have a list of backgrounds colors and I want to use the #each function to output a class name and a number behind it.
Is there a way with Sass to automatically count and add that into the class name?
$colors: blue, red, green;
#each $color in $colors {
.class- {
background: $color;
}
}
So the output would be:
.class-1 {
background: red
}
.class-2 {
background: blue
}
Etc…
This did the trick for me:
#for $i from 1 through length($colors) {
.class-#{$i} {
background: '#{nth($colors, $i)}';
}
}

Using each inside array in sass

I have custom theme colors
$theme-colors-custom: (
abc--bg: #fafafa,
abc--text: #ccc
);
my problem is that I would have to manualy type names (abc--bg,abc--text,...) but I would like to generate them using other variables from below.
I it possible to dinamicly assign color using each, something like this to $theme-colors-custom:
$my-variable-prefix: "abc";
$theme-light-name: 'light';
$theme-dark-name: 'dark';
$body-bg-light: #fafafa;
$body-text-light: #ccc;
$body-bg-dark: #212121;
$body-text-dark: #ddd;
$themes: (
light: (
bg: $body-bg-light,
text: $body-text-light,
),
dark: (
bg: $body-bg-dark,
text: $body-text-dark,
),
);
$theme-colors-custom: (
$name-variables: map-get($themes, 'light');
#each $key, $value in $name-variables {
#{$my-variable-prefix}--#{$key}: #{$value},
}
);
The expected result would be:
$theme-colors-custom: (
abc--bg: #fafafa,
abc--text: #ccc,
);
Yes it is possible, but you need to do the each loop outside of the map and use map-merge:
$theme-colors-custom: ();
$name-variables: map-get($themes, 'light');
#each $key, $value in $name-variables {
$keyName: #{$my-variable-prefix}--#{$key};
$theme-colors-custom: map-merge($theme-colors-custom, ($keyName: $value));
}

Get a variable name as a string

I have a class with the name .text-black, I also have a map with some values.
$black: #000;
map:
dark: $black;
I want to loop through this map and create a new class with the $key and then extend they new class with using the value text-black.
There are 2 problems I have. The first I think I have solved, if I can get the $value as $black instead of #000. Then I can remove the $ using string replacement.
The second challenge however is proving a headache for me. I need to get $black in stead of #000.
Here is my code showing my approach so far.
// String Replacement to remove '$' from varaible name.
#function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
#if $index {
#return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace)
}
#return $string;
}
// get color from map
#function text-color($key: "weekly-digest") {
#return map-get($text-colors, $key);
}
$black: #000000;
// map text-colors
$text-colors: () !default;
$text-colors: map-merge(
(
"news": $black,
),
$text-colors
);
// Extendable classes.
.text-black{
color: $black;
}
// Loop function
#each $name, $value in $text-colors {
&--#{$name} {
background-color: $value;
#extend .text-#{$value} // This should return '.text-black' not '.text-#000000'
}
}
I try to give you 3 different solutions. In all these solutions I used 2 colors (black & red) only to see if they could work in combination:
1. Using a function str-split() (maybe the most intricated, but use your code)
I found a magical function that splits a string in 2 elements How to split a string into two lists of numbers in SASS?.
So my idea is to use that function (thanks to #dayenite: if you like this solution, please upvote him ;)) in a string using a character (in my example "_") to split your maps in 3 different value (something like 2 keys and 1 value):
1. "news"
2. "black"
3. "#000"
Your map could become something like this:
$text-colors: map-merge(
(
"news_black":$black,
"info_red": $red
),
$text-colors
);
This is all the code in action:
#function str-split($string, $separator) {
// empty array/list
$split-arr: ();
// first index of separator in string
$index : str-index($string, $separator);
// loop through string
#while $index != null {
// get the substring from the first character to the separator
$item: str-slice($string, 1, $index - 1);
// push item to array
$split-arr: append($split-arr, $item);
// remove item and separator from string
$string: str-slice($string, $index + 1);
// find new index of separator
$index : str-index($string, $separator);
}
// add the remaining string to list (the last item)
$split-arr: append($split-arr, $string);
#return $split-arr;
}
/* Example with 2 colors */
$black: #000000;
$red: #ff0000;
$text-colors: () !default;
$text-colors: map-merge(
(
"news_black":$black,
"info_red": $red //my add
),
$text-colors
);
// Extendable classes.
.text-black{
color: $black;
}
.text-red{
color: $red;
}
// Loop function
.my-div{
#each $name, $value in $text-colors {
$list: (); // Create every time an empty list with my 2 argoments, for example "news" and "black"
$split-values: str-split($name, "_"); //use the function to split the string
#each $valore in $split-values {
$list: append($list, str-split($valore, " "));
}
//set here the first part of the string (i.e. news/info)
&--#{nth($list, 1)} {
background-color: $value;
#extend .text-#{nth($list, 2)} // set here the second part: black/red
}
}
}
https://www.sassmeister.com/gist/08f699dba4436d3bae6a4d8b666e815b
2. Using a nested list
This time I created a simple nested list with 3 value ("news", "black", $black), the result is the same.
$black: #000000;
$red: #ff0000;
// list text-colors
$text-colors: (
( "news", "black", $black ),
( "info", "red", $red )
);
// Extendable classes.
.text-black{
color: $black;
}
.text-red{
color: $red;
}
.mydiv{
// Loop function
#each $item in $text-colors {
&--#{nth($item, 1)} {
background-color: nth($item, 3);
#extend .text-#{nth($item, 2)}
}
}
}
https://www.sassmeister.com/gist/59adf5ee60ea46dd7a24e94d7db91d85
3. Using a nested map
Here I use nested maps, but the structure is different from yours and I don't know if it's ok for you.
$black: #000000;
$red: #ff0000;
// map text-colors
$text-colors: (
news:(black: $black),
info:(red: $red)
);
.text-black{
color: $black;
}
.text-red{
color: $red;
}
.mydiv{
// Loop function
#each $name, $value in $text-colors {
&--#{$name} {
#each $name-color, $value-color in $value {
background-color: $value-color;
#extend .text-#{$name-color}
}
}
}
}
https://www.sassmeister.com/gist/8ddec08755befc84f6e4846fbc625130
Well, I haven't another ideas. I hope at least one way could help you to solve your problem.
Cheers :)

Pass sass variable inside loop as a selector without value

I want to use a mixin to give me the option to pass additional selectors as parameters as needed, in addition to the selectors already established. But I’m getting an error here. Not sure what I'm missing, unless you just can't use variables inside of a loop without passing a value to each item and I'm going about this all wrong.
#mixin light-section-text( $selectors: null ) {
#if ( $selectors ) {
#for $i from 1 through length( $selectors ) {
#{nth( $selectors, $i )},
}
}
p,
address,
li {
color: $white;
}
}
The desired output of #include light-section-text( "body", "strong", "strong a" ); in this case would be:
body,
strong,
strong a,
p,
address,
li {
color: #fff; }
First, you can't directly pass the selectors list to the mixin function as it would cause $selectors to be the first string. So you have to first declare a list variable and then pass that variable to the function.
Second, you should simply use the Placeholders functionality offered by Sass which makes use of #extend and the % character.
%color{
color: white;
}
#mixin light-section-text( $selectors: null ) {
#if ( $selectors ) {
#for $i from 1 through length( $selectors ) {
#{nth( $selectors, $i )}{
#extend %color;
}
}
}
p,
address,
li {
#extend %color;
}
}
$list-variable: "body", "strong", "strong a";
#include light-section-text($list-variable);
Alternate Method
You don't even need to use the mixin function as this task can be handled by sass placeholder alone.
$white : white;
%color{
color: $white;
}
$list-variable: "body", "strong", "strong a", "p", "address", "li";
#each $item in $list-variable {
#{$item} {
#extend %color;
}
}

Sass mixin with multiple variables attached to the same style

I have a Sass list of class name and color:
$txt-colors:
"music" $color-orange,
"video" $color-green,
"photo" $color-blue;
What I'm currently doing is looping through each line and applying that style to that color
#each $color in $txt-colors {
".#{nth($color, 1)}" {
color: nth($color, 2);
}
}
I now want the ability to be able to pass multiple class names that corresponds to that color that would output something like this:
.music, .instrument {
color: $color-orange;
}
Where the list would now look like:
$txt-colors:
"music" "instrument" $color-orange,
"video" $color-green,
"photo" $color-blue;
I think it would much cleaner if I do it with a mixin that accepts multiple parameters, but how do I do it?
Thanks!
Use another list.
$txt-colors:
("music" "instrument") orange,
"video" green,
"photo" blue;
#each $classes, $color in $txt-colors {
$sel: ();
#each $c in $classes {
$sel: append($sel, '.#{$c}', comma);
}
#{$sel} {
color: $color;
}
}
Alternately, just have the first element in your list be the selector:
$txt-colors:
".music, .instrument" orange,
".video" green,
".photo" blue;
#each $sel, $color in $txt-colors {
#{$sel} {
color: $color;
}
}

Resources