Sass is an incredibly powerful preprocessor and one of it’s main advantages is the use of maps. Maps allow us to store data and quickly generate dynamic styles from this data.

One common use of a map is looping through it’s data using the @each directive to build different components. Plenty has been written about doing this so I won’t go into too much detail there. Instead, I want to share one technique I often my myself using when looping through a map, and that is finding the current position, or index, in the map.

I often use maps to generate icon styles, storing the name of the icon and it’s background-color in the map. Assuming the icons all share the same background-image as a sprite, I need a way to determine the background-position for each icon. One way would be to add this value to the map. There’s a better way though and it’s using the current position in the map to calculate the background-position value.

Finding the Index Position in a Map

Sass comes with a handful of different functions, including those for working with lists and maps. To find the the index position in a map we’ll use the index() function.

The index() function returns the position of a value within a list. However, when using a map, and not a list, the index() function returns the position of a pair in a map.

For this to work the index() function takes a handful of arguments. First, we pass in the map name wrapped in parenthesis, followed by a comma, and then a space separated key and value names pair, also wrapped in parenthesis. The entire function should look like index(($map), ($key $value)). When looping in the @each directive, the current key and value names are available, thus allowing us to find the current position in the map. With this position we can do any calculations we want to set the background-position value.

Below you can see what the Sass map, @each directive, and the index() function look like in practice, as well as what the compiled CSS is.

Sass

1
2
3
4
5
6
7
8
9
10
11
12
13
$networks: (
  "twitter": #1da1f2,
  "facebook": #3c5a99,
  "linkedin": #0071a1
);

@each $network, $color in $networks {
  .#{$network} {
    background-color: $color;
    background-image: url("network-icons.svg");
    background-position: 0 (index(($networks), ($network $color)) * 24px);
  }
}

Compiled CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.twitter {
  background-color: #1da1f2;
  background-image: url("network-icons.svg");
  background-position: 0 24px;
}

.facebook {
  background-color: #3c5a99;
  background-image: url("network-icons.svg");
  background-position: 0 48px;
}

.linkedin {
  background-color: #0071a1;
  background-image: url("network-icons.svg");
  background-position: 0 72px;
}

Another, Less Convenient, Way

Another, less convenient, way to find the current position in a map is to use the index() and map-keys() functions together.

To begin, the map-keys() function takes one argument, $map, which is the variable name of the map and returns a list of all the keys in the map. Then, the index() function takes two arguments, $list and $value, where $list is the list of keys returned by the map-keys() function and $value is the current key provided by the @each directive.

The magic here happens by using the map-keys() function inside the index() function, such as index(map-keys($map), $value). It works however it’s not as convenient as using the index() function alone.

Enjoy

If you’re curious to learn more about some of the finer details Sass and how to maintain CSS feel free to checkout the CSS as a Service: Maintaining Style talk I gave at SXSW and SassConf.