Making Use of Sass’ Zip() Function

Dennis Gaebel
Share

Sass alleviates the need to write repetitive code when it comes to our stylesheets, but you knew that already or else you wouldn’t be reading this far. I want to show you a nice, savvy way to write shorthand properties without the need to remember the order of values for CSS like animation and font.

Before You Begin : Since I’m using Sass maps it might be a good idea to get comfortable with them. It just so happens there are at least two great articles.

Never Memorize What You Can Look Up In A Book

The title you just read is a famous quote from Albert Einstein -and a good one at that. My best guess is that I’m not the only developer in the world asking themselves “Now…does direction come after fill-mode? or is it the other way around?”

The setup that follows might not be for everyone, but I want you to take note of the approach. You could change this to work any way you want. Remember … the sky’s the limit.

Sass

@function sh-setup($config) {
  @return zip(map-values($config)...);
}

$animation_config: (
  name: none,
  duration: 0s,
  timing: ease,
  delay: 0s,
  iteration: 1, // infinite
  direction: normal, // reverse, alternate, alternate-reverse
  fill-mode: none, // forwards, backwards, both
  play-state: running
);

.object {
  animation: sh-setup($animation_config);
}

CSS

.object {
  animation: none 0s ease 0s 1 normal none running;
}

What Happened?

Our sh-setup() function takes an argument called config that passes it’s value to map-values() and the result is finally passed to the zip() function. This function takes a comma separated list returned by map-values() and converts that list into a space separated string! Whoa! Daaaaaannnnnggggg!!!

So…that’s cool and all, but why the three full stops (or ellipsis) at the end of map-values()? Well, the ellipsis says to map-values() “allow multiple values that are comma separated to be passed.” For example, when we strip away zip() from the equation we’ll end up with the following string returned.

none, 0s, ease, 0s, 1, normal, none, running

If we didn’t add ... Sass would output our shorthand incorrectly because zip() can’t accept our multiple comma separated values. It sees the output above as one single string. The ... helps tell Sass to accept an unknown number of arguments in order to strip away the commas. We the developers have to tell Sass it’s alright to split the string into separate cases so we end up with:

none 0s ease 0s 1 normal none running

Going Further

Now that we’ve done it with animation let’s try that same approach with the font shorthand. The font property takes values for it’s shorthand in a very specific order otherwise the entire statement fails. If you don’t recall the order (ha-ha, who does) then let me refresh your memory:

  • font-style
  • font-variant
  • font-weight
  • font-size
  • line-height
  • font-family

Now let’s set this up to work the way we want. Take note we’re not touching our sh-setup() function one bit and instead we’re working around it.

@function sh-setup($config) {
  @return zip(map-values($config)...);
}

$fonts: "'Proxima Nova', Arial, sans-serif";

$font_config: (
  font-style: normal,
  font-variant: normal,
  font-weight: normal,
  font-measurements: 100%/1.5,
  font-family: unquote($fonts)
);

body {
  font: sh-setup($font_config);
}

CSS

font: normal normal normal 100%/1.5 'Proxima Nova', Arial, sans-serif;

I placed font-size and line-height into one variable in order to avoid over complication since we need the / to come in-between the font-size and line height value. The unquote() function is the magic that allows us to output multiple fonts for the font-family property. This function helps preserve the single quotes recommended by the W3C for font family names containing whitespace to avoid mistakes in escaping. We also maintain commas for multiple font-family names.

Another way we could do the previous approach is defining another map to hold our font-families, and still use the same function we’ve been using all along.

@function sh-setup($config) {
  @return zip(map-values($config)...);
}

$fonts: (
  primary-font: "'Proxima Nova'", // font family names containing whitespace write like this"'Font Name'"
  font-fallback1: Helvetica,
  font-fallback2: Arial,
  font-failure: sans-serif
);

$font_config: (
  font-style: normal,
  font-variant: normal,
  font-weight: normal,
  font-measurements: 100%/1.5,
  font-family: unquote(#{map-values($fonts)})
);

body {
  font: sh-setup($font_config);
}

I like the readability in this case and I know exactly what font is intended for display in terms of priorities. The downside is that I had to interpolate map-values() within unquote() making this a bit more complicated for the sake of readability.

Parting Thoughts

Now that we’ve seen these use cases with the animation and font shorthand, where else do you think we could use something like zip()? Could it be used for the background shorthand? How about the grid syntax? It’s really up to you to decide the approach. I hope I’ve inspired you at the very least to investigate other helper functions like zip() available to front-end developers that want to use Sass. As you venture into the unknown keep in mind “A person who never made a mistake never tried anything new.” ~Einstein