Dot notation for dealing with maps
See original GitHub issueI would like to see the ability to use dot notation to call variables from a map. While the new map-get()
in 3.3+ is awesome however it can get to be unreadable real quick.
For example say that you had this map.
$buttons: (
color: #fff,
primary: (
background: #fff,
color: #000
...
),
secondary: (
background: #000,
...
)
);
Currently to call that you can use map-get()
like this.
.button{
background: map-get($buttons, background);
color: map-get($buttons, color);
&-primary{
background: map-get(map-get($buttons, primary), background);
&:hover{
background: lighten(map-get(map-get($buttons, primary), background), 10%);
}
}
...
}
This example isn’t to bad but when you start calling functions inside of functions inside of functions inside of functions things get out of hand quickly and become really hard to follow. Especially if you are adding and subtracting things to get elements to line up correctly
top: em(nth-val(map-get($messaging, padding), 1) - map-get($messaging, line-height), map-get($messaging, font-size)) * -1;
If we had dot notation for calling variables It would make things like this more readable.
top: em(nth-val($messaging.padding, 1) - $messaging.line-height, $messaging.font-size) * -1
This comes in to play even more if you have a map that is more than 2 levels deep.
$example-map: (
foo: (
baz: (
qux: (
quux: (
garply: (
waldo: "Hello world"
)
)
)
)
)
);
Currently to get waldo
in the $example-map
you would do this
content: map-get(map-get(map-get(map-get(map-get(map-get($example-map, foo), baz), qux), quux), garply), waldo);
Using dot notation you could get it like this.
content: $example-map.foo.baz.qux.quux.garply.waldo;
I realize this example is a little excessive but I hope it shows how useful it could be.
You shouldn’t have to worry about old sass code not working with this change since you can’t currently have a .
in a variable name.
You would still be able to use interpolation with the variables.
@mixin button-theme($theme){
background: $buttons.#{$theme}.background;
color: $buttons.#{$theme}.color;
}
You should still have the ability to combine the dot notation with the other awesome map functions.
$map-to-merge: (
fred: "",
plugh: "",
xyzzy: "",
thud: ""
);
$temp: map-merge($example-map.foo.bar, $map-to-merge)
Issue Analytics
- State:
- Created 9 years ago
- Reactions:1
- Comments:37
Top GitHub Comments
Sorry in advance for the lengthy post, but someone need to do it. This is a reply to #1739 (comment). @HugoGiraudel, @davidkpiano, @ArmorDarks I understand that sass is a function based language and that’s part of the reason I love using it because it makes doing difficult tasks easy; however using functions alone to handle maps and lists can make what should be simple tasks seem overly complicated. In my issue #1349 I suggested using dot/bracket notation for variables only, and the way I suggested it to be implemented would not interfere with the sass ecosystem and instead be a huge improvement to the best preprocessor available. The longer implementing dot/bracket notation is ignored, the bigger the issue becomes. There are several notable libraries out there that have implemented their own way of handling maps, including some that @HugoGiraudel has written. The mere fact that there have been so many libraries attempting to solve this problem should be a clear indicator that it’s an issue worth standardizing. It also means everyone learns how to handle large sass maps in a different way, and therefore every time someone moves jobs they have to change the way they deal with sass maps and that means relearning something that should have been implemented from the start. These various implementations make it harder to understand what’s going on in people’s code, and it make it even more difficult for new people who are trying to learn sass to understand what they are seeing.
@davidkpiano Is 100% correct
map-get($map, foo.bar)
is a very bad idea. That’s why I didn’t suggest using dot notation in this way. However, if you implement dot notation similarly to how other notable languages use dot notation, it would solve these ridiculous problems everyone runs in to with maps.In
js
and other languages that use dot/bracket notation you can’t add.
into the variable/key name for good reason, and it’s pretty much the same point that @davidkpiano is trying to make. The difference being sass does follow suit and doesn’t accept.
in a variable/key name. If you tried to set a map key to befoo.bar
you will get an error. The reason it returns an error is because sass interprets it as a css selector and since a css selector can’t be followed by:
an error is returned. Variables can’t have a dot in them either for the same reason. So how does his example work? Well a sass key can be a type ofstring
,list
,number
,color
, ormap
. This means we can set a key to anything we want, and that allows us to do things like he’s showing in his example. The reason his example works is becausenth(&, 1)
is a type oflist
. So whenmap-get($map, nth(&, 1))
is called it’s looking for key that matches the list ofnth(&, 1)
. If you absolutely have to have a.
in your key name then you can do the same thing other languages do; just add quotes around the declaration to note that it’s a string"foo.bar"
— and that makes the key valid.Here’s @davidkpiano example explained in depth, and the live example is on sassmiester if you would like to see the output
These use cases can still use dot/bracket notation without any special functions being added
Implementing dot/bracket notation is something that needs to happen. It would make sass tremendously more readable, and it would make it easier for beginners with background knowledge of
js
and other languages that use dot/bracket notation easier to dive in to sass because they don’t have to re-learn the same concept of structures/maps in a different way than they already know. The reason why I started using sass is because of it’s extensibility, simplicity, and ease of understanding. The way maps(aka structures) are currently implemented makes it more complex than it needs to be. While I understand sass maps and use them on a daily basis, trying to teach a developer how to use sass map functions is harder than it needs to be and every time each developer has said "Well why didn’t they just use dot notation? That would be so much easier!”. I believe if there was a poll on implementing dot/bracket notation in sass and it was asked on all the major sass resource sites and email lists the majority of sass developers would agree that sass needs dot/bracket notation.Examples and use cases
Here are some more examples and use cases, how they are written with the current implementation of maps, and how they could be written using dot/bracket notation:
Setting a key value using other values from the same map.
Here is a live example that I had to use on codepen.
With map functions
With dot/bracket notation
Calling a dynamic key
This would be a use case for mixins and functions to call a key based off an argument that was passed:
With map functions
With dot/bracket notation
Getting a variable from a deeply nested map
This example is taken from the original post
With map functions
With dot/bracket notation
Setting a value on a deeply nested key
This example uses the same map from the original post.
With functions
The only real possibility to do this is to use a third party functions, like the one that @HugoGiraudel wrote and shared on sitepoint, or the one that was written by @Snugug for Sass-maps, or another that was written by @cahnory for PlastiCSS, or the one that was written by @pascalduez gist, these are just a few I came across in a single post by @chriscoyier on csstricks and there are so many more out there, this was just from the first link in google.
With dot/bracket notation
Using
map-remove
with nested mapWith map functions
With dot/bracket notation
Using
map-keys
, andmap-values
on a nested mapWith map functions
With dot/bracket notation
Using
map-has-key
on a nested mapWith map functions
With dot/bracket notation
Bracket notation for sass lists
The bracket notation should also be applied to sass lists because it’s still dealing with the same concept of getting and setting things in variables.
Getting/setting an item in a list(aka array)
With list functions
With bracket notation
Since sass isn’t zero based like js the first item in the array would still be accesed through
1
and the last element would be accesed by the length of the listGetting/setting an item in a list(aka array) that is nested in a map
With map/list functions
With dot/bracket notation
Dot notation is a very simple concept to understand regardless of your coding background, as it is already very common in several other languages. This would make it easer for other developers to learn sass, and utilize the power of sass maps. Implement it correctly would reduce the amount of wasted time by developers creating their own implementations of the sass map functions, as well as definitively solve a problem that others have already tried to hack their way around.
@mistersender Of course that is none of my business, but if your choice of CSS preprocessor relies on the ability to use dot-notation, I am afraid you missed the point.