sass-site/source/documentation/values/maps.html.md.erb

182 lines
5.7 KiB
Plaintext
Raw Normal View History

2018-09-01 22:35:20 +02:00
---
title: Maps
table_of_contents: true
2018-09-01 22:35:20 +02:00
---
Maps in Sass hold pairs of keys and values, and make it easy to look up a value
by its corresponding key. They're written `(<expression>: <expression>,
<expression>: <expression>)`. The [expression](../syntax/structure#expressions)
before the `:` is the key, and the expression after is the value associated with
that key. The keys must be unique, but the values may be duplicated. Unlike
[lists](lists), maps *must* be written with parentheses around them. A map with
no pairs is written `()`.
2018-09-01 22:35:20 +02:00
<% fun_fact do %>
Astute readers may note that an empty map, `()`, is written the same as an
empty list. That's because it counts as both a map and a list. In fact, *all*
maps count as lists! Every map counts as a list that contains a two-element
list for each key/value pair. For example, `(1: 2, 3: 4)` counts as `(1 2, 3
4)`.
2018-09-01 22:35:20 +02:00
<% end %>
Maps allow any Sass values to be used as their keys. The [`==` operator][] is
used to determine whether two keys are the same.
[`==` operator]: ../operators/equality
<% heads_up do %>
Most of the time, it's a good idea to use [quoted strings][] rather than
[unquoted strings][] for map keys. This is because some values, such as color
names, may *look* like unquoted strings but actually be other types. To avoid
confusing problems down the line, just use quotes!
2018-09-01 22:35:20 +02:00
[quoted strings]: strings#quoted
[unquoted strings]: strings#unquoted
2018-09-01 22:35:20 +02:00
<% end %>
## Using Maps
Since maps aren't valid CSS values, they don't do much of anything on their own.
That's why Sass provides a bunch of [functions][] to create maps and access the
values they contain. With
[functions]: ../modules/map
2018-09-01 22:35:20 +02:00
### Look Up a Value
Maps are all about associating keys and values, so naturally there's a way to
get the value associated with a key: the [`map.get($map, $key)` function][]!
2018-09-01 22:35:20 +02:00
This function returns the value in the map associated with the given key. It
returns [`null`][] if the map doesn't contain the key.
[`map.get($map, $key)` function]: ../modules/map#get
2018-09-01 22:35:20 +02:00
[`null`]: null
2018-10-23 22:01:12 +02:00
<%= partial 'code-snippets/example-map-get' %>
2018-09-01 22:35:20 +02:00
### Do Something for Every Pair
This doesn't actually use a function, but it's still one of the most common ways
to use maps. The [`@each` rule][] evaluates a block of styles for each key/value
pair in a map. The key and the value are assigned to variables so they can
easily be accessed in the block.
2019-04-04 01:38:26 +02:00
[`@each` rule]: ../at-rules/control/each
2018-09-01 22:35:20 +02:00
<%= partial 'code-snippets/example-each-map' %>
2018-10-23 22:01:12 +02:00
### Add to a Map
2018-09-01 22:35:20 +02:00
It's also useful to add new pairs to a map, or to replace the value for an
existing key. The [`map.merge($map1, $map2)` function][] does this: it returns a
2018-09-01 22:35:20 +02:00
new map that contains all the key/value pairs in *both* arguments.
[`map.merge($map1, $map2)` function]: ../modules/map#merge
2018-09-01 22:35:20 +02:00
<% example(autogen_css: false) do %>
@use "sass:map";
$light-weights: ("lightest": 100, "light": 300);
$heavy-weights: ("medium": 500, "bold": 700);
@debug map.merge($light-weights, $heavy-weights);
// (
// "lightest": 100,
// "light": 300,
// "medium": 500,
// "bold": 700
// )
===
@use "sass:map"
$light-weights: ("lightest": 100, "light": 300)
$heavy-weights: ("medium": 500, "bold": 700)
@debug map.merge($light-weights, $heavy-weights)
// (
// "lightest": 100,
// "light": 300,
// "medium": 500,
// "bold": 700
// )
2018-09-01 22:35:20 +02:00
<% end %>
`map.merge()` is often used with an inline map to add a single key/value pair.
2018-09-01 22:35:20 +02:00
<% example(autogen_css: false) do %>
@use "sass:map";
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
2018-09-01 22:35:20 +02:00
@debug map.merge($font-weights, ("extra-bold": 900));
// ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
===
@use "sass:map"
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
2018-09-01 22:35:20 +02:00
@debug map.merge($font-weights, ("extra-bold": 900))
// ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
2018-09-01 22:35:20 +02:00
<% end %>
If both maps have the same keys, the second map's values are used in the map
that gets returned.
<% example(autogen_css: false) do %>
@use "sass:map";
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
2018-09-01 22:35:20 +02:00
@debug map.merge($font-weights, ("medium": 600));
// ("regular": 400, "medium": 600, "bold": 700)
===
@use "sass:map"
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
2018-09-01 22:35:20 +02:00
@debug map.merge($font-weights, ("medium": 600))
// ("regular": 400, "medium": 600, "bold": 700)
2018-09-01 22:35:20 +02:00
<% end %>
Note that because Sass maps are [immutable][], `map.merge()` doesn't modify the
2018-09-01 22:35:20 +02:00
original list.
[immutable]: #immutability
## Immutability
Maps in Sass are *immutable*, which means that the contents of a map value never
changes. Sass's map functions all return new maps rather than modifying the
originals. Immutability helps avoid lots of sneaky bugs that can creep in when
the same map is shared across different parts of the stylesheet.
You can still update your state over time by assigning new maps to the same
variable, though. This is often used in functions and mixins to track
configuration in a map.
<% example(autogen_css: false) do %>
@use "sass:map";
$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms);
@mixin add-browser-prefix($browser, $prefix) {
$prefixes-by-browser: map.merge($prefixes-by-browser, ($browser: $prefix));
}
@include add-browser-prefix("opera", o);
@debug $prefixes-by-browser;
// ("firefox": moz, "safari": webkit, "ie": ms, "opera": o)
===
@use "sass:map";
$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms)
@mixin add-browser-prefix($browser, $prefix)
$prefixes-by-browser: map.merge($prefixes-by-browser, ($browser: $prefix))
@include add-browser-prefix("opera", o)
@debug $prefixes-by-browser
// ("firefox": moz, "safari": webkit, "ie": ms, "opera": o)
<% end %>