Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Navigate a nested maps with map-fetch() in Sass
// ----
// Sass (v3.3.0.rc.2)
// Compass (v1.0.0.alpha.17)
// ----
//
// map-fetch($map, $keys)
//
// An easy way to fetch a deep value in a multi-level map. Works much like
// map-get() except that you pass multiple keys as the second parameter to
// go down multiple levels in the nested map.
//
@function map-fetch($map, $keys) {
$key: nth($keys, 1);
$length: length($keys);
$value: map-get($map, $key);
@if ($length > 1) {
$rest: ();
@for $i from 2 through $length {
$rest: append($rest, nth($keys, $i))
}
@return map-fetch($value, $rest)
} @else {
@return $value;
}
}
$config: (
themes: (
mist: (
header: #dcfac0,
content: #00968b,
footer: #85c79c
),
spring: (
header: #f4fac7,
content: #c2454e,
footer: #ffb158
)
)
);
@each $theme in map-keys(map-get($config, themes)) {
.#{$theme} {
.header { background-color: map-fetch($config, themes $theme header ); }
.content { background-color: map-fetch($config, themes $theme content ); }
.footer { background-color: map-fetch($config, themes $theme footer ); }
}
}
.mist .header {
background-color: #dcfac0;
}
.mist .content {
background-color: #00968b;
}
.mist .footer {
background-color: #85c79c;
}
.spring .header {
background-color: #f4fac7;
}
.spring .content {
background-color: #c2454e;
}
.spring .footer {
background-color: #ffb158;
}
@agrobbin

This comment has been minimized.

Copy link

@agrobbin agrobbin commented Aug 11, 2014

@jlong here is a newer version of this nested fetching:

@function map-deep-get($map, $keys...) {
  $value: $map;
  @each $key in $keys {
    $value: map-get($value, $key);
  }
  @return $value;
}

In your example above, you could do this to get the mist header color #dcfac0:

map-deep-get($config, "themes", "mist", "header");
@Jim-Domco

This comment has been minimized.

Copy link

@Jim-Domco Jim-Domco commented Dec 18, 2014

+1, Great function! Had the exact same thought about themes and found this before I wrote my own. Thanks for the time-saver!

@dernetzjaeger

This comment has been minimized.

Copy link

@dernetzjaeger dernetzjaeger commented Jan 12, 2015

Great! Exactly what I was looking for!

@geekiam

This comment has been minimized.

Copy link

@geekiam geekiam commented Jan 16, 2015

+1, Thanks for the saving my time ☺️

@Dan503

This comment has been minimized.

Copy link

@Dan503 Dan503 commented Feb 7, 2015

THANK YOU! 😄

@strarsis

This comment has been minimized.

Copy link

@strarsis strarsis commented Nov 23, 2015

Could this be moved into a repository and published as eyeglass module on npm?

@callumflack

This comment has been minimized.

Copy link

@callumflack callumflack commented Mar 19, 2016

@agrobbin this is great. As I don't completely understand it, is there any chance you could write an error warning into it?

@jessicaschilling

This comment has been minimized.

Copy link

@jessicaschilling jessicaschilling commented Dec 28, 2017

Thaaaaaank you!

@dallas

This comment has been minimized.

Copy link

@dallas dallas commented Feb 6, 2018

What’s the advantage of this over something more standard & built-in like:

Input:

$config: (
  themes: (
    mist: (
      header: #dcfac0,
      content: #00968b,
      footer: #85c79c
    ),
    spring: (
      header: #f4fac7,
      content: #c2454e,
      footer: #ffb158
    )
  )
);

@each $theme-name, $theme-values in map-get($config, themes) {
  .#{$theme-name} {
    @each $section, $color in $theme-values {
      .#{$section} { background-color: $color; }
    }
  }
}

Output:

.mist .header {
  background-color: #dcfac0;
}
.mist .content {
  background-color: #00968b;
}
.mist .footer {
  background-color: #85c79c;
}

.spring .header {
  background-color: #f4fac7;
}
.spring .content {
  background-color: #c2454e;
}
.spring .footer {
  background-color: #ffb158;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment