Hi, there! Today, you will learn how to create responsive font sizes with Sass maps and @each
method.
I hope you enjoy it!
Let's start with a map and we can dive into more complex concepts with @each
operation.
First of all, create a map that contains font sizes for 2 different screen sizes. Call them sm
and lg
, which stand for small and large screen sizes respectively. Both should contain the same key with different values.
If you don't know what Sass map is, it is equivalent to object in JavaScript or dictionary in Python.
_type-scale.scss
$type-scale: (
sm: (
300: 0.875rem,
400: 1rem,
500: 1.125rem,
600: 1.375rem,
700: 2rem,
),
lg: (
300: 1rem,
400: 1.125rem,
500: 1.375rem,
600: 2rem,
700: 2.75rem,
),
);
Okay, you might probably know that one good way to create responsive font sizes in CSS is with custom properties. And, their value can be easily changed. It looks something like this:
example.css
:root {
--fs-300: 0.875rem;
--fs-400: 1rem;
--fs-500: 1.125rem;
--fs-600: 1.375rem;
--fs-700: 2rem;
}
@media only screen and (min-width: 50em) {
:root {
--fs-300: 1rem;
--fs-400: 1.125rem;
--fs-500: 1.375rem;
--fs-600: 2rem;
--fs-700: 2.75rem;
}
}
It is easy to change the value of custom properties at any given point. However, with Sass, we have what we call variables whose value are quite tough to change. That said, we can use the superpower of Sass, which will help us to generate those custom properties. You might be saying what is the point of making things complicated even though at the end of the day we end up with these custom properties. It's true, but, Sass is like an organized version of CSS and provides features that makes the code more robust and organized.
Okay, let's get back to the topic. Our final goal is to turn the map (in _type-scale.scss
) into custom properties (in example.css
). Whenever you see or use Sass maps, you might probably have seen @each
rule. It is because they work very well together. You can describe them as arrays with map()
or forEach
functions in JavaScript.
So, start by creating a @each
rule. It will take 3 parameters.
- 1st: key in the map
- 2nd: value in the map
- 3rd: the map itself
Note: You can name key and value whatever you want, but you need to specify which map you are using.
It looks something like this:
each-example.scss
$colors: (
primary: #06f,
secondary: #333,
accent: #f70,
);
@each $key, $value in $colors {
.text-#{$key} {
color: $value;
}
}
Compiled CSS:
each-example.css
.text-primary {
color: #06f;
}
.text-secondary {
color: #333;
}
.text-accent {
color: #f70;
}
#{$key}
- this weird looking thing is called Interpolation. It is used to inject values into strings. You can learn more about it here.
As you can see, Sass is a truly powerful language. If we describe CSS as JavaScript, Sass can be seen as React.
Ok, I hope you got the idea of how @each
and maps work very well together. Now, let's generate our responsive font sizes.
Create a @each
rule that loops through $type
map and generate following output:
example.css
:root {
--fs-300: 0.875rem;
--fs-400: 1rem;
--fs-500: 1.125rem;
--fs-600: 1.375rem;
--fs-700: 2rem;
}
@media only screen and (min-width: 50em) {
:root {
--fs-300: 1rem;
--fs-400: 1.125rem;
--fs-500: 1.375rem;
--fs-600: 2rem;
--fs-700: 2.75rem;
}
}
You need to use nested
@each
rule for nested maps! Also, you might need to use@if
and@else
rules. You can learn more about them here. Yes, we have if statements in Sass, too.:)
Okay, start with the first layer of @each
rule and see what it will output.
style.scss
@use 'type-scale' as *;
:root {
@each $key, $value in $type-scale {
--#{$key}: $value;
}
}
Compiled CSS:
style.css
:root {
--sm: $value;
--lg: $value;
}
Whenever you see that it returns $value
in CSS, just interpolate it.
style.scss
@use 'type-scale' as *;
:root {
@each $key, $value in $type-scale {
--#{$key}: #{$value};
}
}
Now, out of nowhere you will get an error, saying it is not valid CSS. Becuase $key
is returning screen sizes (sm, lg), and $value
is trying to return another map inside those keys. Let's create one more @each
and see what it will return.
Dont' forget that
$value
is returning inner map, so the second@each
should be relative to$value
.
style.scss
:root {
@each $screen-size, $sizes in $type-scale {
@each $key, $value in $sizes {
--fs-#{$key}: #{$value};
}
}
}
If you remember, in the first layer of @each
, $key
returned screen sizes (sm, lg) and $value
returned another map, containing all the sizes of each key. So, I called $key
as $screen-size
and $value
as $sizes
.
Now, in our inner @each
rule, we are asking it to return keys and values inside those sizes.
Compiled CSS:
style.css
:root {
--fs-300: 0.875rem;
--fs-400: 1rem;
--fs-500: 1.125rem;
--fs-600: 1.375rem;
--fs-700: 2rem;
--fs-300: 1rem;
--fs-400: 1.125rem;
--fs-500: 1.375rem;
--fs-600: 2rem;
--fs-700: 2.75rem;
}
Okay, we are getting there. A few things left to do. Now, we need to find which key belongs to sm
or lg
screen sizes. And, here @if
and @else
come very handy.
So, $screen-size
return screen-sizes (sm, lg). If it returns sm
, just return it inside the :root
. Else return it inside the media-query.
You need to use
@if
and@else
statements after the first layer of@each
rule, not the second!. If it satisfies, return the second layer of@each
rule that we wrote above.
style.scss
@use 'type-scale' as *;
:root {
@each $screen-size, $sizes in $type-scale {
@if $screen-size == sm {
@each $key, $value in $sizes {
--fs-#{$key}: #{$value};
}
} @else {
@media (min-width: 50em) {
@each $key, $value in $sizes {
--fs-#{$key}: #{$value};
}
}
}
}
}
Compiled CSS:
style.css
:root {
--fs-300: 0.875rem;
--fs-400: 1rem;
--fs-500: 1.125rem;
--fs-600: 1.375rem;
--fs-700: 2rem;
}
@media (min-width: 50em) {
:root {
--fs-300: 1rem;
--fs-400: 1.125rem;
--fs-500: 1.375rem;
--fs-600: 2rem;
--fs-700: 2.75rem;
}
}
Yes, we did it! As you might have guessed, we can add more screen sizes. And, it is a task for you if you want to give it a shot.
If you have any doubts, questions or feedback, please do consider sharing it with me. I really appreciate it and get back to you as soon as possible!
If you are new to Sass maps and @each
method, I highly recommend checking out Kevin Powell's video where he explained the superpower of Sass with custom properties and utility classes. It is where I learned these cool things, too.:)
- Custom props & utility classes by Kevin Powell
That's it! I hope you liked it!
You can get the source code from this GitHub repo
If you've liked this article, please do consider sharing it with others. It means the world to me
Top comments (0)