mirror of
https://github.com/danog/sass-site.git
synced 2024-12-11 17:09:52 +01:00
165 lines
6.9 KiB
Markdown
165 lines
6.9 KiB
Markdown
|
---
|
||
|
title: Sass 3.3 is Released
|
||
|
author: Natalie Weizenbaum
|
||
|
tags: blog
|
||
|
#date: 2014-03-07 16:40 PST
|
||
|
---
|
||
|
|
||
|
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
|
||
|
in [the changelog](/documentation/file.SASS_CHANGELOG.html), but there are three
|
||
|
that I want to draw your attention to in particular.
|
||
|
|
||
|
# Maps in SassScript
|
||
|
|
||
|
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
|
||
|
$map: (
|
||
|
key1: value1,
|
||
|
key2: value2,
|
||
|
key3: value3,
|
||
|
);
|
||
|
```
|
||
|
|
||
|
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,
|
||
|
there are a number of [new built-in
|
||
|
functions](/documentation/Sass/Script/Functions.html#map_functions) that allow
|
||
|
user-defined mixins and functions to use them. Here are a few particularly
|
||
|
useful ones:
|
||
|
|
||
|
- `map-get($map, $key)` looks up a value in a map using its key. For example,
|
||
|
using the example above, `map-get($map, key2)` would return `value2`.
|
||
|
|
||
|
- `map-merge($map1, $map2)` merges two maps together. The keys in `$map2`
|
||
|
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:
|
||
|
new-value, key2: value2, key3: value3)`.
|
||
|
|
||
|
- `map-remove($map, $key)` removes a value in a map. For example,
|
||
|
`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;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
# Source Maps
|
||
|
|
||
|
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.
|
||
|
|
||
|
# More Flexible `&`
|
||
|
|
||
|
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.
|
||
|
|
||
|
# Deprecation: Variable Scope and `!global`
|
||
|
|
||
|
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.
|
||
|
|
||
|
# That's All
|
||
|
|
||
|
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
|
||
|
changelog](/documentation/file.SASS_CHANGELOG.html#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!
|
||
|
|
||
|
[^1]:
|
||
|
Some languages call them "hashes", "dictionaries", or "associative
|
||
|
arrays". JavaScript calls them "objects" for weird historical reasons.
|