5 Great Uses for Sass Maps

Share this article

The Sass map is an awesome tool for organizing your code, minimizing duplication, and making your code base less prone to overall careless errors. They allow us to outline and document our projects in a way that helps with their overall architecture. Maps first came about in Sass 3.3, and have transformed the way developers structure their code. Last year, Hugo wrote a great post about using Sass maps, that I would recommend you also take a look at.

Please note that a Sass sourcemap is not the same thing as a Sass map. Both of these features came out in the same release, and are sometimes confused for each other.

Basic Usage

Maps are surrounded by parenthesis () and are structured in key: value pairs. They are accessed with map-get() and can be nested within each other, allowing for organization of grouped content.

$map-name: (
  key-1: val-1,
  key-2: val-2,
  key-3: val-3
);

So now that we understand the basic structure, let’s dive into five practical strategies for organizing our code that take advantage of maps!

1. Lucid Layering

Let’s start out with some basic map usage. Maps are great for organizing your code, and one place in which this organization is really useful is when dealing with layers of elements in your project (i.e. the z-index).

$layers: (
  modal: 8,
  logo: 7,
  header: 6,
  footer: 5,
  sidebar: 4,
  caption: 3,
  image: 2,
  text: 1
);

Now we can clearly see where all of our elements will lie in relation to each other. Then, we can access this map with the following mixin:

@mixin layer($layer-name) {
  z-index: map-get($layers, $layer-name);
};

And use it as such:

header {
  @include layer('header');
}

2. Color Management

Remember when I said that maps were great for nesting and organizing groups of information? Well let’s put that into practice with color management! Say we have a color palette with specified tints and shades (lighter and darker variations on a base color).

$colors: (
  'red': (
    tint: #f66,
    base: #c00,
    shade: #a00
  ),
  'orange': (
    tint: #f94,
    base: #f50,
    shade: #f12
  ),
  'yellow': (
    tint: #ffa,
    base: #ff0,
    shade: #ff5
  )
);

We can then write a function to grab the colors we want:

@function color($color-name, $tone: base) {
    @return map-get(map-get($colors, $color-name), $tone);
}

This function will read the map for our color and return the base by default. If we input a value for tone, then we get the tint of the color on the map. So background: color('yellow', 'tint') will return the lighter shade. As a (very legible) example,

// .scss
h1 {
  background: color('yellow');
  color: color('red', 'shade');
}

becomes:

h1 {
  background: #ff0;
  color: #a00;
}

You can also begin to label shades by number or any other various naming technique that makes sense to your project.

3. Media Queries

After a bit of surveying on Twitter, I came up with a conclusion on how breakpoint variables should best be named. The old ideology of naming involved device-specific breakpoints such as $phone, $desktop, or $browser. Then, people started realizing that this is a bad strategy – the web is fluid, and one can’t assume what “size” a phone will come in, so they started naming variables small, medium, and large. But these don’t make that much sense either.

Instead, I like the approach of taking the most notable layout change and naming your media queries based on that change. For example, if your layout changes from one column to two, name that media query mq--2-col, and if your major change is the text centering, it can be called $mq--content-center.

An aside: when using variables in the open, I like to prefix them within groups i.e. color--, mq--, or layer--.

Yet, to manage these names even better, we can use a map.

$breakpoints: (
  1-col: 0px,
  left-align-text: 400px,
  2-col: 680px,
  wide-header: 900px
);

Can you see what is going on here? Like an outline, the breakpoints map tells the story of what happens as our page expands. From the smallest point (this is optional, I just included it to prove a point), we have a 1-column, centered-text layout. As it hits 400px, the text aligns left. At 680px, we split into a 2-column layout. At 900px, the header converts into a wide-format iteration. We can see the major layout changes just from reading this map.

And now for a mixin to use the map:

@mixin smaller-than($point-name) {
  $width: map-get($breakpoints, $point-name);
  @media (max-width: $width) {
    @content;
  }
}

@mixin larger-than($point-name) {
  $width: map-get($breakpoints, $point-name);
  @media (min-width: $width) {
    @content;
  }
}

//usage
.heading {
  font-size: 2em;
  @include smaller-than(left-text-align) {
    font-size: 1.5em;
  }
  @include larger-than(2-col) {
    font-size: 3em;
  }
}

4. Accesible Icons

If you are using an icon font (such as IcoMoon) for some simple icons (such as social media icons) on your site, the code for that can be really, really ugly. You can make a quick icon map, mapping the characters for the icons to a class.

$icon-map: (
  dribbble: '\e601',
  facebook: '\e607',
  instagram: '\e60c',
  twitter: '\e602',
  github: '\e603'
);

This way, you can quickly create classes and accessible icons using pseudo-elements by using something like this:

@each $name, $visual in $icon-map {
  .icon--#{$name} {
    font-size: 0;

    &:before {
      font-size: 1rem;
      font-family: 'IcoMoon';
      content: $visual;
    }
  }
}

This generates each icon as a :before pseudo-element, linked to a class name of icon- while making the text of the actual element invisible to the eye, but still legible to screen readers. Meanwhile, the graphic element of the icon remains visible by setting that font-size separately.

So if we have this line of HTML: <div class="icon--facebook">facebook</div>, we will only see the facebook icon mapped to the character \e607.

5. Pattern Libraries

Another great use of maps is for building pattern libraries. One of the biggest complaints developers have against pattern libraries is that they are bulky and full of heavy code, unused by an individual. We don’t want to include any code that we aren’t actually using in order to make our CSS more performant.

Well, maps can fix that! Because maps are just a data structure and don’t output any code until we use map-get to access them, they are perfect for this!

Take animations, for instance. You can structure your animations in a map.

$animations: (
  'fade-in': (
    0%: (
      opacity: 0
    ),
    100%: (
      opacity: 1
    )
  ),
  'fade-flicker': (
    0%: (
      opacity: 1
    ),
    30%: (
      opacity: 0
    ),
    60%: (
      opacity: 1
    ),
    78%: (
      opacity: 0
    ),
    100%: (
      opacity: 1
    )
  )
);

Now unlike keyframes, none of this will output any code until we ask for it to. So currently, there are no keyframes available for us within our project. To mitigate this, let’s make a few mixins and a new map for the animations we will include in our project.

@mixin keyframe-gen($name) {
  @keyframes #{$name} {
    @each $position, $change in map-get($animations, $name) {
      #{$position} {
        @each $prop, $val in $change {
          #{$prop}: #{$val};
        }
      }
    }
  }
};

$included-animations: ();

@mixin animate($name, $duration: 2s, $timing: ease-in) {
  $exists: index($included-animations, '#{$name}');
  @if not $exists {
    @at-root {
      @include keyframe-gen($name);
    }
    $included-animations: append($included-animations, '#{$name}') !global;
  }

  animation: $name $duration $timing;
};

What this is doing is writing out the animation to be included in our project as well as setting that animation to be called on the element. There are no repetitions and our code stays true to a need-to-use output basis. To demonstrate:

.fade-me-in {
  @include animate('fade-in');
}

.also-fade-me-in {
  @include animate('fade-in', 3s);
}

And our only output will be:

@keyframes fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

.fade-me-in {
  animation: "fade-in" 2s ease-in;
}

.also-fade-me-in {
  animation: "fade-in" 3s ease-in;
}

Maps As Outlines

Clearly, Sass maps are pretty great. They are a data structure which you can use to really help you map out (all of the puns intended) your project and display a summary of its various aspects in a neat and orderly fashion. The biggest advantage is their organizational structure (which acts as an outline for various aspects of your project) and that maps never output any code until called to do so. So try out some of these techniques, and comment with your own ideas for using maps!

Frequently Asked Questions about Sass Maps

What are the key benefits of using Sass Maps?

Sass Maps are a powerful feature in Sass (Syntactically Awesome Stylesheets) that allows you to store multiple values in a single variable. This can be incredibly useful for managing complex data structures in your stylesheets. For instance, you can use Sass Maps to store and manipulate color schemes, font stacks, or responsive breakpoints in a more efficient and maintainable way. They also help in reducing repetition and improving the readability of your code.

How do I create a Sass Map?

Creating a Sass Map is straightforward. You start by defining a variable and then assign a list of key-value pairs to it. Here’s a simple example:

$colors: (
primary: #333,
secondary: #666,
tertiary: #999
);
In this example, ‘primary’, ‘secondary’, and ‘tertiary’ are the keys, and ‘#333’, ‘#666’, and ‘#999’ are the corresponding values.

How can I access values in a Sass Map?

You can access values in a Sass Map using the map-get function. For example, to get the value of ‘primary’ from the ‘$colors’ map, you would use:

color: map-get($colors, primary);

Can I nest Sass Maps?

Yes, Sass Maps can be nested. This means you can have a map within a map. Nested maps can be useful for organizing complex data structures. To access values in a nested map, you can use the map-get function in combination with the map-deep-get function.

How can I iterate over a Sass Map?

You can iterate over a Sass Map using the @each directive. This allows you to loop through each key-value pair in the map. Here’s an example:

@each $key, $value in $colors {
.#{$key}-text {
color: $value;
}
}

Can I modify a Sass Map?

Yes, you can modify a Sass Map using the map-merge function. This function allows you to add new key-value pairs to an existing map or update the values of existing keys.

What are some common use cases for Sass Maps?

Sass Maps are commonly used for managing color schemes, font stacks, grid layouts, and responsive breakpoints. They can also be used for creating design systems or style guides.

Can I use Sass Maps with other Sass features?

Yes, Sass Maps can be used in combination with other Sass features like mixins, functions, and directives. This allows you to create more complex and powerful stylesheets.

Are there any limitations to using Sass Maps?

While Sass Maps are incredibly powerful, they do have some limitations. For instance, you cannot use a map as a CSS value. Also, maps are not fully supported in all versions of Sass, so you need to ensure that your version of Sass supports maps.

Where can I learn more about Sass Maps?

There are many resources available online to learn more about Sass Maps. The official Sass documentation is a great place to start. You can also find tutorials and articles on websites like SitePoint, W3Schools, and Indeed.

Una KravetsUna Kravets
View Author

Una Kravets is a Front End Developer currently residing in Austin, Texas. She co-founded the SassyDC and ATXSass meet-ups, is a core member of the Open Design Foundation team, and is a big advocate of performance-first design.

animationsmedia queriessasssass mapsStuR
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week