Adventure seekers describe a map as a guide. A symbolic depiction highlighting relationships between elements of some space, such as objects. To travelers, maps are a must and soon you’ll discover the powerful benefits of using maps as well, but with Sass. Sass maps are about to become your new BFF and here’s why.
Maps in Sass
Introduced in Sass 3.3, maps represent an association between keys and values within an object. Maps must always be surrounded by parentheses and the key/value pairings inside must always be comma-separated. Once a map has been created authors have the ability to loop through the map (or not) and distribute these key/value pairings at will. Both the key and the value in Sass maps can be any SassScript object (native Sass functions that allow authors to manipulate code). Here’s what the basic structure looks like…
$map: (
key1: value1,
key2: value2,
key3: value3
);
@each $key, $value in $map {
.element--#{$key} {
background: $value;
}
}
By using the powers of descriptive words(wink, wink) I hope the example above makes sense. As we loop through our map using @each
, the first value is the map’s key followed by the key’s value and finally the variable ($map
) representing our map. It’s also good to note that we don’t always need a loop to obtain the map’s keys/values, but it’s good to see how a loop can be used.
Maps In Real Life
Discussing how something works is one thing, but seeing how it can be used in real life is a different beast entirely. I’m the type that needs to see some real action and foo
nor bar
will do. Let’s take a look at some real cases using real words to describe real things.
Multiple Transition Values
Transitions have the ability to receive multiple values separated by a comma so lets take a transition that might be used widely across our system and make a map representing the behavior we’re trying to achieve.
Sass
$card_morph: (
trans1: 200ms transform ease-in-out,
trans2: 400ms background ease-in,
trans3: 600ms color linear
);
.card {
transition: map-values($card_morph);
}
CSS Output
.card {
-webkit-transition: 200ms -webkit-transform ease-in-out, 400ms background ease-in, 600ms color linear;
transition: 200ms transform ease-in-out, 400ms background ease-in, 600ms color linear;
}
The function map-values()
used above works like this…it will return a list of all values in a map comma-separated (not including the keys). The parameter accepted is the map itself so in this case that’s the variable we defined called $card_morph
. Also take note that we’re not using a loop in this case. We’re simply using the Sass Script Function
natively built into the language.
Multiple Maps, One Loop
We can use multiple maps within one loop as well. This can be great for objects that carry properties in relation to one another. In this case, eye color and font based on the particular name of a person.
Sass
$eye_color: (
jeremy: #0989cb,
beth: #8666ae,
matt: #02bba7,
ryan: #ff8178
);
$font: (
jeremy: Helvetica,
beth: Verdana,
matt: Times,
ryan: Arial
);
@each $key, $value in $eye_color {
.#{$key} {
background: $value;
font-family: map-get($font, $key);
}
}
CSS Output
.jeremy {
background: #0989cb;
font-family: Helvetica;
}
.beth {
background: #8666ae;
font-family: Verdana;
}
.matt {
background: #02bba7;
font-family: Times;
}
.ryan {
background: #ff8178;
font-family: Arial;
}
I’m sure you may have noticed the SassScript Function map-get()
from the loop above. The map-get
function allows authors to retrieve the value of the key requested. The first parameter is the map desired and the second is the key of the map requested. This is why we can obtain the output of another map from the same loop since the keys in both maps are identical.
Config Maps
Here’s an example I use in my demo for a Google Material Design interaction. In this case we use maps as a configuration object in order to obtain and set the different properties of the object.
Sass
$google_materialshadow_ambient: (
shadow1: 0 1px 1.5px rgba(0, 0, 0, 0.12),
shadow2: 0 1px 1px rgba(0, 0, 0, 0.24)
);
$google_materialshadow: (
ambient: map-values($google_materialshadow_ambient)
);
$google_expando_proportions: (
icon_size: 24px,
card_size: 340px
);
.google-expando__icon {
box-shadow: map-get($google_materialshadow, ambient);
height: map-get($google_expando_proportions, icon_size);
width: map-get($google_expando_proportions, icon_size);
}
Hopefully by now things are starting to look familiar. Nothing has changed in what’s being used it’s just a different approach to a different context. We’re still using map-get()
and map-values()
, but we’re using our maps to hold and store information based on characteristics of an object. Also note the use of a map ($google_materialshadow_ambient
) within a map ($google_materialshadow
) in order to store the type of shadow effect we desire.
Icon Fonts
Want a DRY approach to write and generate content for your pseudo trickery in order to achieve icon font bliss?
Sass
$icons: (
menu: "\fXXX",
delete: "\fXXX",
search: "\fXXX"
);
@each $icon, $unicode_value in $icons {
.transformicons-#{$icon}:before {
content: $unicode_value;
}
}
Tracking Layers
Here’s a fun way to track your z-index issues. In this case I’m using a table and sandwich as a means to convey meaning to my layers. Keep in mind z-index works much like items on a table.
Sass
$layers: (
ground: -3,
basement: -2,
floor: -1,
table: 0,
bottom_bun: 1,
condiment: 2,
cheese: 3,
meat: 4,
top_bun: 5
);
.container {
position: relative;
z-index: map-get($layers, table);
}
.container__modal {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: map-get($layers, top_bun);
}
HTML
<div class="container">
This is the container
<div class="container__modal">This is the modal</div>
</div>
Do you have an amazing way to use a Sass map? Leave a comment and help us discover the deepest power of our new BFF.
Another great example and use case of a Sass map can be seen on my Cascader demo on CodePen that takes a comma separated list returned by
map-values()
and uses thezip()
method to convert the comma separated list into a space separated list for the animation property.Clever. I like it.
Thanks Hugo.