2023-03-01 20:46:05 +01:00
|
|
|
---
|
|
|
|
title: Sass 3.3 is Released
|
|
|
|
author: Natalie Weizenbaum
|
2023-03-03 16:39:31 +01:00
|
|
|
date: 2014-03-07 16:40:00 -8
|
2023-03-01 20:46:05 +01:00
|
|
|
---
|
|
|
|
|
|
|
|
After ironing out a bunch of bugs in numerous release candidates, we're finally
|
|
|
|
ready to release Sass 3.3.0, codename Maptastic Maple, for public consumption.
|
|
|
|
This release has a lot of exciting new features that you can read about in full
|
2023-06-20 17:20:07 +02:00
|
|
|
in [the
|
|
|
|
changelog](https://github.com/sass/ruby-sass/blob/stable/doc-src/SASS_CHANGELOG.md),
|
|
|
|
but there are three that I want to draw your attention to in particular.
|
2023-03-01 20:46:05 +01:00
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
## Maps in SassScript
|
2023-03-01 20:46:05 +01:00
|
|
|
|
|
|
|
As language designers, most of our job is to listen to feedback from users and
|
|
|
|
act upon it. This is tricker than it sounds: users are very good at knowing the
|
|
|
|
precise thing that they want to accomplish, but they tend not to have a sense of
|
|
|
|
how that fits into the big picture. So we take a large volume of user requests,
|
|
|
|
try to distill the core needs that aren't being met, and see if we can come up
|
|
|
|
with features that hit as many of those as possible as simply as possible.
|
|
|
|
|
|
|
|
SassScript maps are a great example of this. We had a lot of users requesting
|
|
|
|
things like variable interpolation, so they could write things like
|
|
|
|
`$#{$theme-name}-background-color`. Other users wanted built-in functions that
|
|
|
|
worked with lists of pairs, or a way to get the name of a variable that was
|
|
|
|
passed to a function. We eventually realized the underlying feature that people
|
|
|
|
actually wanted: a way to associate values with names.
|
|
|
|
|
|
|
|
Most programming languages have a notion of maps[^1], which are associations
|
|
|
|
from "key" objects to "value" objects. Sass 3.3 adds support for these as a
|
|
|
|
first-class data structure. The syntax is designed to be very similar to that
|
|
|
|
used for `@media` queries. They look like this:
|
|
|
|
|
|
|
|
```scss
|
2023-03-09 17:19:39 +01:00
|
|
|
$map: (key1: value1, key2: value2, key3: value3);
|
2023-03-01 20:46:05 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
Unlike lists, maps must always be surrounded by parentheses. `()`, which
|
|
|
|
previously referred to an empty list, now _also_ refers to an empty map; both
|
|
|
|
list and map operations will work on it.
|
|
|
|
|
|
|
|
Maps can't be used as CSS values, since they aren't valid CSS syntax. However,
|
2023-06-20 17:20:07 +02:00
|
|
|
there are a number of [new built-in functions](/documentation/modules/map/) that
|
|
|
|
allow user-defined mixins and functions to use them. Here are a few particularly
|
2023-03-01 20:46:05 +01:00
|
|
|
useful ones:
|
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
* `map-get($map, $key)` looks up a value in a map using its key. For example,
|
2023-03-01 20:46:05 +01:00
|
|
|
using the example above, `map-get($map, key2)` would return `value2`.
|
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
* `map-merge($map1, $map2)` merges two maps together. The keys in `$map2`
|
2023-03-01 20:46:05 +01:00
|
|
|
overwrite those in `$map1`, so this is also a good way to add values to a map.
|
|
|
|
For example, `map-merge($map, (key1: new-value))` would return `(key1:
|
2023-03-09 17:19:39 +01:00
|
|
|
new-value, key2: value2, key3: value3)`.
|
2023-03-01 20:46:05 +01:00
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
* `map-remove($map, $key)` removes a value in a map. For example,
|
2023-03-01 20:46:05 +01:00
|
|
|
`map-remove($map, $key)` would return `(key: value2, key3: value3)`.
|
|
|
|
|
|
|
|
In addition to the new map functions, all the existing list functions also work
|
|
|
|
on maps. The list functions will see each map as a list of pairs. For example,
|
|
|
|
`nth($map, 1)` will return `(key1 value1)`. Not only that, but `@each` has new
|
|
|
|
syntax for working with both maps and lists of pairs. For example:
|
|
|
|
|
|
|
|
```scss
|
|
|
|
@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
|
|
|
|
#{$header} {
|
|
|
|
font-size: $size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
produces:
|
|
|
|
|
|
|
|
```css
|
|
|
|
h1 {
|
|
|
|
font-size: 2em;
|
|
|
|
}
|
|
|
|
|
|
|
|
h2 {
|
|
|
|
font-size: 1.5em;
|
|
|
|
}
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
font-size: 1.2em;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
## Source Maps
|
2023-03-01 20:46:05 +01:00
|
|
|
|
|
|
|
Continuing the map theme, Sass 3.3 comes with support for generating source maps
|
|
|
|
when compiling to CSS. Source maps are a standard format for telling browsers
|
|
|
|
how files they consume got generated. For Sass, this means that browsers'
|
|
|
|
development tools can now tell you exactly which line of your Sass source file
|
|
|
|
each style rule came from. Currently this is only well-supported in Chrome, but
|
|
|
|
hopefully other browsers will add support soon.
|
|
|
|
|
|
|
|
When compiling Sass from the command line, all you need to do to generate source
|
|
|
|
maps is pass the `--sourcemap` flag. Sass will automatically generate a
|
|
|
|
`.css.map` file next to the generated `.css` file. All you have to do then is
|
|
|
|
make sure your `.scss` or `.sass` file is visible to the browser, and you'll be
|
|
|
|
good to go.
|
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
## More Flexible `&`
|
2023-03-01 20:46:05 +01:00
|
|
|
|
|
|
|
When we released Sass 3.0, we added support for SCSS, which meant we had to
|
|
|
|
actually parse all the selectors in the document. This meant that you couldn't
|
|
|
|
just plop the parent selector, `&`, anywhere in a selector. Overall this was an
|
|
|
|
improvement: it caught more errors and encouraged users to write more flexible
|
|
|
|
mixins.
|
|
|
|
|
|
|
|
Unfortunately, it also made one important use-case harder. With the rise in
|
|
|
|
popularity of [BEM](http://gembem.com/), [OOCSS](http://oocss.org/), and
|
|
|
|
[SMACSS](http://smacss.com/), people became more and more interested in adding
|
|
|
|
suffixes to classes. When using Sass, they wanted to write mixins to do this,
|
|
|
|
and the restrictions on `&` made that very hard to do.
|
|
|
|
|
|
|
|
In Sass 3.3, we're loosening these restrictions. You can now write `&-suffix`
|
|
|
|
(or `&_suffix`, or even `&suffix` if you really want) and Sass will make it
|
|
|
|
work. If this fails to apply—for example, if `&` is `*`—Sass will
|
|
|
|
print a helpful error message.
|
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
## Deprecation: Variable Scope and `!global`
|
2023-03-01 20:46:05 +01:00
|
|
|
|
|
|
|
We don't always get everything right the first time, and in order to make Sass
|
|
|
|
the best language it can be we occasionally have to change old behavior.
|
|
|
|
Sometimes this happens in ways that might make existing stylesheets stop
|
|
|
|
functioning, so we have a policy of printing warnings for stylesheets that are
|
|
|
|
going to change in the future.
|
|
|
|
|
|
|
|
Sass 3.3 adds a number of deprecations, but the biggest one by far has to do
|
|
|
|
with the way variable scope works. Up until now, when you wrote `$var: value` in
|
|
|
|
a function, mixin, or CSS rule in Sass, it could do one of two things. If there
|
|
|
|
was a global variable named `$var`, it would overwrite that variable. Otherwise,
|
|
|
|
it would create a local variable that was only visible within the current set of
|
|
|
|
curly braces.
|
|
|
|
|
|
|
|
This was a pretty big problem, since any given variable assignment could
|
|
|
|
potentially be modifying a variable that it had no way of knowing existed. We
|
|
|
|
want to migrate to a better system where assigning to a variable in a local
|
|
|
|
scope won't overwrite a global variable unless the assignment explicitly says to
|
|
|
|
do so, as in `$var: value !global`.
|
|
|
|
|
|
|
|
In order to avoid breaking existing stylesheets, we haven't made this change
|
|
|
|
yet. Instead, if a global variable is overwritten by a local declaration, we now
|
|
|
|
print a deprecation warning suggesting that the user add `!global`. Right now,
|
|
|
|
`!global` doesn't do much other than make the warning go away, but in a future
|
|
|
|
release it will work as I described above.
|
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
## That's All
|
2023-03-01 20:46:05 +01:00
|
|
|
|
|
|
|
Actually, there's a lot more, but that's all I have room for in this post. If
|
|
|
|
you want to see the full assortment of new features, check out [the
|
2023-06-20 17:20:07 +02:00
|
|
|
changelog](https://github.com/sass/ruby-sass/blob/stable/doc-src/SASS_CHANGELOG.md#330-7-march-2014).
|
|
|
|
You can also play with the new features on
|
|
|
|
[SassMeister](http://sassmeister.com/) or on your own computer by running `gem
|
|
|
|
update sass`. Enjoy!
|
2023-03-01 20:46:05 +01:00
|
|
|
|
2023-03-09 17:19:39 +01:00
|
|
|
[^1]: Some languages call them "hashes", "dictionaries", or "associative
|
2023-03-01 20:46:05 +01:00
|
|
|
arrays". JavaScript calls them "objects" for weird historical reasons.
|