Colin Bacon, web developer.

Sass maps: A better function for retrieving values

Sass maps: A better function for retrieving values

The @each directive in Sass is used to loop through a map or list. This post gives an example of how we can use this to get values from nested maps.

The original method

In my previous post How to use Sass maps, I gave an example with nested maps and a function to retrieve the values from them. Here's the function.

@function socialSet($set, $key){
  @return map-get(map-get($social, $set), $key);
}

We call map-get twice to allow us the retrieve the nested values. This works perfectly fine but feels a bit clunky. It is also quite brittle, the function can only be used for a nested map one level deep. Should we wish to change the structure of our map, it could break our Sass.

A better way

I happened to come across this Stack Overflow question about iterating nested maps. The solution uses the @each directive to iterate through the map. This feels like a nicer, more elegant approach so let's apply it to our example.

Instead of calling map-get on map-get we can use @each to do the work for us. Lets consider this example.

$map: $social; // the name of our map

@each $key in twitter, colour {
    $map: map-get($map, $key);
}

Our keys to iterate are twitter, colour. We initially set $map to the name of the map we want to use, in this case $social. With each iteration $map is set to the value returned from map-get. That value is then used as the map parameter for the next iteration. In the last iteration $map is set to the value we wish to retrieve.

Here's the final function.

@function mapGet($map, $list...) {
    @each $key in $list {
        $map: map-get($map, $key);
    }
    @return $map; // Our value
}

// usage
.smokey {
    color: mapGet(social, twitter, colour);
}

// outputs
.smokey {
    background-color: #eee;
}

If you wondered what $list... is, it is a variable argument this allows a function/mixin to take a variable number of arguments (our list to loop through).

Summary

By using @each to loop through a set of keys, we are able to produce a generic function to retrieve values from maps of any structure whether they are nested or not. A definite improvement on the original function!