Welcome back to series about SASS/SCSS. If you like this content, this is a link for you follow other articles about this topic. Series about SASS/SCSS
In this
article, we discuss about @each in SASS/SCSS.
Table of
contents:
- What is @each?
- @each with list
- @each with map
- @each with destructuring
- Nested @each
Let’s go to
the content!
Do we have a
list of elements, a map of key, value pairs or we have destructuring that holds
multiple values in an element, in many programming languages we have loops
like forEach, for, while, do while that allow iterations through the elements
in those lists, maps. Similarly, in SASS/SCSS we also have loops like that. So,
we already know why we should use loops. Now let's go into how to use them. First,
we will learn about @each in SASS/SCSS.
What is
@each?
We have a
syntax to use @each that is @each <variable> in <expression>. With
@each representing whether we want to use @each in iterating list, map or
destructuring. Next, <variable> is the name of the variable that
represents the values that each element can iterate over. If in a list, each
element we can repeat a value, then we name <variable> to represent the
value we get. As for a map, we have key and value pairs, we initialize two
variables to represent the key and value pairs that we get. Or in the case
where we have destructuring with more than two values in an iterable element,
we initialize the corresponding number of variables to represent the values
an element iterates over. Finally, we have “in <expression>”,
<expression> can be a list, map or destructuring and “in” represents
whether we use loop in that list, map or destructuring.
@each with
list
To better
understand the uses of @each in SASS/SCSS, let's look at the following example:
// index.scss
$color-list: red, green, blue;
@each $clr in $color-list {
.btn-#{$clr} {
background-color: $clr;
}
}
We have a
list of colors, including three colors: red, green, blue. Then we will use
@each to iterate over each element in this list. We initialize the variable
“$clr” to represent the value that each element iterates and get “in
$color-list”. The syntax is quite simple and easy to understand. We perform
that task is to get the colors and assign them to "background-color"
and the classes will be named according to the name of that color. Let's see
what the result we get will be:
/* index.css */
.btn-red {
background-color: red;
}
.btn-green {
background-color: green;
}
.btn-blue {
background-color: blue;
}
The result
is exactly what we want, classes "btn" are assigned the name of the
color and have a "background-color" of the same color.
@each
with map
In the above
problem, we use @each to iterate through the list of colors to, using colors.
However, if to change those colors to hex, rgb, hsl color codes, the above case
is no longer accurate, and we will get an error in SASS/SCSS compiling the code
for us. To solve the above problem and another feature of SASS/SCSS, we use a
map containing key, value pairs with key being the name of color and value
being the value of color which can be hex code, rgb, hsl. And let's see an
example how to use @each to traverse each element in a map:
// index.scss
$color-map: (
primary-clr: #345,
secondary-clr: #897,
accent-clr: #456
);
@each $key, $value in $color-map {
.btn-#{$key} {
background-color: $value;
}
}
We have a
map named “$color-map”, we use @each to start iterating map. We initialize two
variables that are $key, $value corresponding to the value that each element
has. Then we use $key in the class name and $value will be the value for the
background-color property, let's see what the result will be.:
/* index.css */
.btn-primary-clr {
background-color: #345;
}
.btn-secondary-clr {
background-color: #897;
}
.btn-accent-clr {
background-color: #456;
}
Completely
consistent with the requirements we have set out. So we can get the setting of
variables that match the values in the list or map, making it easy to
retrieve the values.
@each
with destructuring
Not stopping
there, @each also helps us do more difficult things. Let's come to the example
of destructuring. No longer limited to key-value pairs only. But we can also
initialize more variables to get more value in an element.
// index.scss
$color-destructuring:
primary-clr #345 #eee 18px,
secondary-clr #897 #fff 20px,
accent-clr #456 #fef 17px
;
@each $name, $bg-clr, $clr, $font-size in $color-destructuring {
.btn-#{$name} {
background-color: $bg-clr;
color: $clr;
font-size: $font-size;
}
}
In the
example above we have a destructuring named “$color-destructuring” with 4
values in a word part. We have name, background-color, color, font-size.
Every time @each iterates over an element we get the above four values, we
initialize four variables that can represent each value we get, and we get the
result:
/* index.css */
.btn-primary-clr {
background-color: #345;
color: #eee;
font-size: 18px;
}
.btn-secondary-clr {
background-color: #897;
color: #fff;
font-size: 20px;
}
.btn-accent-clr {
background-color: #456;
color: #fef;
font-size: 17px;
}
Awesome! Not
only can we iterate through elements with keys and values, but we can also
traverse by destructuring with more values in an element, this value will
depend on you defining a destructuring, maybe an element will contain three,
four or more values, if you can control them well. So, we've seen how @each
works. However, there will be a case in destructuring that happens, that is
when we name the variables that represent the values, we can traverse that do
not match the number we get.?
// index.scss
$color-destructuring:
primary-clr #345 #eee 18px,
secondary-clr #897 #fff 20px,
accent-clr #456 #fef 17px
;
@each $name, $bg-clr, $font-size in $color-destructuring {
.btn-#{$name} {
background-color: $bg-clr;
font-size: $font-size;
}
}
We use the
above example again and we see that, we omit the $color value and we just take
the value of $font-size, let's see the value we get will be:
/* index.css */
.btn-primary-clr {
background-color: #345;
font-size: #eee;
}
.btn-secondary-clr {
background-color: #897;
font-size: #fff;
}
.btn-accent-clr {
background-color: #456;
font-size: #fef;
}
Wow! The
result we get is that the values are taken in turn, although we intentionally
omit a value, however, the SASS/SCSS compiler still takes consecutive values.
Likewise, if we initialize more variables than we retrieve, what will be the
result?
// index.scss
$color-destructuring:
primary-clr #345 #eee 18px,
secondary-clr #897 #fff 20px,
accent-clr #456 #fef 17px
;
@each $name, $bg-clr, $clr, $font-size, $space in $color-destructuring {
.btn-#{$name} {
background-color: $bg-clr;
color: $clr;
font-size: $font-size;
padding: $space;
}
}
In the above
example, we have taken out a variable $space and we set the property as
padding. Let's see the results we get when we have absolutely no value.
/* index.css */
.btn-primary-clr {
background-color: #345;
color: #eee;
font-size: 18px;
}
.btn-secondary-clr {
background-color: #897;
color: #fff;
font-size: 20px;
}
.btn-accent-clr {
background-color: #456;
color: #fef;
font-size: 17px;
}
Nothing
happened. So, we already know that when setting the variable variable, @each
will take turns, when we set the excess, the values will be taken just enough
with the value we have set.
Nested
@each
The problem
will become a little more complicated, we no longer must deal with a map, we
will deal with a nested map. And let's see how we will handle the nested map?
// index.scss
$color-map: (
danger: (
color: orange,
background-color: red,
),
success: (
color: green,
background-color: green
)
);
@each $key, $value in $color-map {
.btn-#{$key} {
@each $k, $v in $value {
#{$k}: #{$v}
}
}
}
In the above
example we have a parent map of “$color-map”, this map contains child maps as
danger, success as modifiers. We use the @each loop for the parent map, we get
the key, value pairs. We can predict that the key will be “danger”, “success”
and the value will be the values of the child maps. We use the keys obtained
from the parent map to name the class. And use value as a child map to make
properties for these classes. Let's see what the result will be:
/* index.css */
.btn-danger {
color: orange;
background-color: red;
}
.btn-success {
color: green;
background-color: green;
}
Awesome!
Both @each work well and using nested map still meets our needs.
Conclusion
We just went
through an analysis of @each in SASS/SCSS. We already know the basic syntax of
@each. Applying @each in iterating lists, maps or more difficult is
destructuring. Besides that, we've covered other exceptions and nested @each.
If you have any
ideas, feel free to comment below. Thank you for joining with me. Having a good
day!
0 Nhận xét