HTML and CSS course Β· Module 7: SASS
Maps and Lists in Sass
In this lesson5
Imagine that your temple needs five text sizes, four colors and four responsive breakpoints. With variables alone you end up with a dozen loose declarations such as $size-1 and $color-primary, and you write every helper class by hand. Sass offers two data structures that organize such values: lists and maps. Think of them like treasure catalogs in an Egyptian temple: lists are ordered inventories, and maps are catalogs with descriptions.
Lists in Sass
A list is a collection of values separated by spaces or commas, like a papyrus scroll listing the names of pharaohs. Below you will see both kinds of separators and a first loop that walks through a list with the @each directive:
1// Space-separated list
2$spacing: 4px 8px 16px;
3
4// Comma-separated list (font names)
5$font-stack: Helvetica, Arial, sans-serif;
6
7// Comma-separated list
8$sizes: 12px, 14px, 16px, 18px, 24px;
9
10// Iterating over a list with @each
11@each $size in $sizes {
12 .text-#{$size} {
13 font-size: $size;
14 }
15}The @each loop takes each element of the $sizes list in turn and generates a class for it, so after compilation you get rules from .text-12px to .text-24px. The #{$size} notation is interpolation, which inserts the variable's value into the selector name. The $spacing list, with values separated by spaces, works exactly the same way, only the separator differs.
Built-in functions help you work with lists:
length($list)- returns the number of elementsnth($list, $index)- returns the element at the given index (index starts from 1)append($list, $value)- adds an element to the endjoin($list1, $list2)- merges two lists
Now let's get the second element of a list of colors with the nth() function:
1$colors: red, blue, green;
2
3.element {
4 color: nth($colors, 2); // blue
5}Index 2 points to blue, because in Sass we count from one, not from zero as in JavaScript. Remember also that lists in Sass are immutable: append() and join() do not modify the original, they return a new list that you need to store in a variable.
Maps in Sass
A map is a collection of key-value pairs, like a secret catalog of Egyptian artifacts in which every item has its label. We define it using parentheses and separate the pairs with commas:
1$breakpoints: (
2 "mobile": 320px,
3 "tablet": 768px,
4 "desktop": 1024px,
5 "wide": 1440px
6);
7
8$colors: (
9 "primary": #2C3E50,
10 "secondary": #D4AF37,
11 "accent": #E74C3C,
12 "background": #F5F0E1
13);The quoted keys are names, and the values stand after the colons. The definition itself, just like an ordinary variable, generates no CSS.
To retrieve a value from a map, we use the map-get() function, which takes the map and a key:
1.header {
2 background-color: map-get($colors, "primary");
3 color: map-get($colors, "secondary");
4}The header gets the #2C3E50 background and the golden #D4AF37 text. You can write the key in single or double quotes, because Sass treats them the same. Watch out for typos, though: for a key that does not exist, map-get() returns null, and a declaration with that value simply disappears from the CSS, without any error.
In new projects you will also meet the module syntax: after adding @use "sass:map" at the top of the file you write map.get($colors, "primary"). It works identically, and global functions such as map-get() are marked as deprecated in newer versions of Dart Sass. I recommend the module syntax although the older one is still everywhere in documentation and older code.
Iterating Over Maps with @each
The real power of maps shows in a loop. The @each directive can take the key and the value at the same time, so we can automatically generate classes based on a map:
1@each $name, $color in $colors {
2 .text-#{$name} {
3 color: $color;
4 }
5 .bg-#{$name} {
6 background-color: $color;
7 }
8}After compilation, we get classes such as .text-primary, .text-secondary, .bg-primary and so on. Adding a new color to the map is enough for the loop to write both classes for it.
Maps for Breakpoints
One of the most common uses of maps is storing breakpoints and using them in media queries. The mixin below takes the width from the map, and the @content directive places the block passed with @include inside the media query:
1$breakpoints: (
2 "sm": 576px,
3 "md": 768px,
4 "lg": 1024px,
5 "xl": 1200px
6);
7
8@mixin respond-to($breakpoint) {
9 $value: map-get($breakpoints, $breakpoint);
10 @media (min-width: $value) {
11 @content;
12 }
13}
14
15.container {
16 width: 100%;
17
18 @include respond-to("md") {
19 width: 750px;
20 }
21
22 @include respond-to("lg") {
23 width: 970px;
24 }
25}The compiler turns each call into an ordinary media query, for example @media (min-width: 768px) with a width of 750px for .container. From now on you change the breakpoints in one place, and names like "md" are easier to read than raw pixels.
Useful Map Functions
map-get($map, $key)- retrieves a valuemap-has-key($map, $key)- checks if a key existsmap-keys($map)- returns a list of keysmap-values($map)- returns a list of valuesmap-merge($map1, $map2)- merges two maps
Maps and lists are higher-level code organization tools. They let you store configuration in one place and generate styles automatically, like an efficient resource management system in an ancient temple. Try adding turquoise to the $colors map and compiling the stylesheet, and the loop will create the .text-turquoise and .bg-turquoise classes by itself.
Remember: a list is an inventory of treasures, and a map is a labeled catalog from which map-get() hands out exactly the item you ask for.
Code for this lesson: index.html
1<!DOCTYPE html>
2<html lang="en">
3<head><title>HTML Forms</title></head>
4<body style="background:#d4a574;font-family:serif;padding:20px;color:#3d2914">
5<h1>HTML Forms</h1>
6<form><label>Scribe's name: <input type="text"></label></form>
7</body>
8</html>Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. How do you retrieve a value from a SASS map called $colors for the key 'primary'?