Exploring Maps In Sass 3.3 (Part 1)
Exploring Maps In Sass 3.3 (Part 1)
Micah Godbolt | Developer
March 17, 2014
Sass is already the home to a wide variety of data types. Numbers, strings, lists, colors, and boolean already cover most our needs. But, as our frameworks started to evolve, we realized this list was missing one key tool: the associative array.
Here is a simple list assigned to the variable $objects.
$objects: (carrot, salt, chicken);
Lists are great for capturing multiple pieces of data, but without associated keys, we had no way to assign context, or retrieve data by any means other than an index. So lets look at how we can create these associative arrays (called Maps in Sass).
Here are those same three values, along with keys, assigned to $objects variable.
$objects: (vegetable: carrot, mineral: salt, animal: chicken);
As you can see, this is very similar to the list syntax. You can even perform list functions on it. $objects is a variable that holds 3 values, each with a unique key. If we want to retrieve the value of salt, we don’t need to know its position, we simply pass in its key along with the name of the map.
$just-a-pinch-of: map-get($objects, mineral); // $just-a-pinch-of == salt
So why is this new data type so valuable? Let’s look at an example.
Organizing Variables
How many times have you seen a list of variables like this?
$primary-nav-top-padding: .2em;
$primary-nav-top-margin: .2em;
$primary-nav-line-height: 1.3;
$secondary-nav-background: white;
$secondary-nav-color: black;
Maps provide us with a means to organize these flat, overflowing lists.
$primary-nav: (
padding-top: .2em,
margin-top: .2em,
line-height: 1.3,
);
$secondary-nav: (
background: white,
color: black,
);
This simple bit of nesting creates some much needed visual separation between each set of variables. It also makes it possible to work with them as a set.
// Sass
@mixin print-styles($map){
@each $property, $value in $map {
#{$property}: $value;
}
}
.primary-nav {
@include print-styles($primary-nav);
}
// Outputted CSS
.primary-nav {
padding-top: .2em;
margin-top: .2em;
line-height: 1.3;
}
Let's Go Deeper
Need more variation? Maps can hold any data type, including other maps!
// Sass
$primary-nav: (
padding-top: .2em,
margin-top: .2em,
line-height: 1.3,
nav-item: (
color: white,
is-expanded: (
padding-top: 1em,
margin-top: 1em
)
)
);
@mixin print-styles($map, $keys...){
$i: 1;
$length: length($keys);
@while $length >= $i {
$map: map-get($map, nth($keys, $i));
$i: $i + 1;
}
@each $property, $value in $map {
@if type-of($value) != map {
#{$property}: $value;
}
}
}
nav.expanded {
@include print-styles($primary-nav, nav-item, is-expanded);
}
This print-styles mixin dives into a your map, traversing down each sub-map until you run out of $keys . At that point it loops through all of the properties, and prints them out one by one.
// Outputted CSS
nav.expanded {
padding-top: 1em,
margin-top: 1em,
}
This single variable can hold properties for every variation, or child of the primary navigation without resorting to using $main-navigation-nav-item-is-expanded-is-hovered-margin-top-on-the-blog-page
.
In the upcoming week we will look at some more use cases for maps including memorization, enhancing the map-get function and using variables to call other variables.