diff --git a/data/documentation.yml b/data/documentation.yml
index 67013fbd2..62f1c7a96 100644
--- a/data/documentation.yml
+++ b/data/documentation.yml
@@ -14,6 +14,8 @@ toc:
- Interpolation: /documentation/interpolation
- At-Rules: /documentation/at-rules
:children:
+ - @use
: /documentation/at-rules/use
+ - @forward
: /documentation/at-rules/forward
- @import
: /documentation/at-rules/import
- @mixin
and @include
: /documentation/at-rules/mixin
- @function
: /documentation/at-rules/function
@@ -64,4 +66,5 @@ toc:
:children:
- Dart Sass: /documentation/cli/dart-sass
- Ruby Sass: /documentation/cli/ruby-sass
+ - Migrator: /documentation/cli/migrator
- JavaScript API: /documentation/js-api
diff --git a/source/documentation/at-rules/forward.html.md.erb b/source/documentation/at-rules/forward.html.md.erb
new file mode 100644
index 000000000..ac5b32d85
--- /dev/null
+++ b/source/documentation/at-rules/forward.html.md.erb
@@ -0,0 +1,5 @@
+---
+title: "@forward"
+introduction: >
+ TODO(nweiz): Write this
+---
diff --git a/source/documentation/at-rules/import.html.md.erb b/source/documentation/at-rules/import.html.md.erb
index 542addc1c..0b02f75ab 100644
--- a/source/documentation/at-rules/import.html.md.erb
+++ b/source/documentation/at-rules/import.html.md.erb
@@ -18,6 +18,48 @@ required to have quotes.
[indented syntax]: ../syntax#the-indented-syntax
+<% heads_up do %>
+ The Sass team discourages the continued use of the `@import` rule. Sass will
+ [gradually phase it out][] over the next few years, and eventually remove it
+ from the language entirely. Prefer the [`@use` rule][] instead.
+
+ [gradually phase it out]: https://github.com/sass/sass/blob/master/accepted/module-system.md#timeline
+ [`@use` rule]: use
+
+ #### What's Wrong With `@import`?
+
+ The `@import` rule has a number of serious issues:
+
+ * `@import` makes all variables, mixins, and functions globally accessible.
+ This makes it very difficult for people (or tools) to tell where anything is
+ defined.
+
+ * Because everything's global, libraries must prefix to all their members to
+ avoid naming collisions.
+
+ * [`@extend` rules][] are also global, which makes it difficult to predict
+ which style rules will be extended.
+
+ [`@extend` rules]: extend
+
+ * Each stylesheet is executed and its CSS emitted *every time* it's
+ `@import`ed, which increases compilation time and produces bloated output.
+
+ * There was no way to define private members or placeholder selectors that
+ were inaccessible to downstream stylesheets.
+
+ The new module system and the `@use` rule address all these problems.
+
+ #### How Do I Migrate?
+
+ We've written a [migration tool][] that automatically converts most
+ `@import`-based code to `@use`-based code in a flash. Just point it at your
+ entrypoints and let it run!
+
+ [migration tool]: /documentation/cli/migrator
+
+<% end %>
+
<% example do %>
// foundation/_code.scss
code {
@@ -414,3 +456,89 @@ for example based on mixin parameters.
@include google-font("Droid Sans")
<% end %>
+
+## Import and Modules
+
+<%= partial '../snippets/module-system-status' %>
+
+Sass's [module system][] integrates seamlessly with `@import`, whether you're
+importing a file that contains `@use` rules or loading a file that contains
+imports as a module. We want to make the transition from `@import` to `@use` as
+smooth as possible.
+
+[module system]: use
+
+### Importing a Module-System File
+
+When you import a file that contains `@use` rules, the importing file has access
+to all members (even private members) defined directly in that file, but *not*
+any members from modules that file has loaded. However, if that file contains
+[`@forward` rules][], the importing file will have access to forwarded members.
+This means that you can import a library that was written to be used with the
+module system.
+
+[`@forward` rules]: forward
+
+<% heads_up do %>
+ When a file with `@use` rules is imported, all the CSS transitively loaded by
+ those is included in the resulting stylesheet, even if it's already been
+ included by another import. If you're not careful, this can result in bloated
+ CSS output!
+<% end %>
+
+#### Import-Only Files
+
+An API that makes sense for `@use` might not make sense for `@import`. For
+example, `@use` adds a namespace to all members by default so you can safely use
+short names, but `@import` doesn't so you might need something longer. If you're
+a library author, you may be concerned that if you update your library to use
+the new module system, your existing `@import`-based users will break.
+
+To make this easier, Sass also supports *import-only files*. If you name a file
+`.import.scss`, it will only be loaded for imports, not for `@use`s. This
+way, you can retain compatibility for `@import` users while still providing a
+nice API for users of the new module system.
+
+<% example(autogen_css: false) do %>
+ // _reset.scss
+
+ // Module system users write `@include reset.list()`.
+ @mixin list() {
+ ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+ }
+ ---
+ // _reset.import.scss
+
+ // Legacy import users can keep writing `@include reset-list()`.
+ @forward "reset" as reset-*;
+ ===
+ // _reset.sass
+
+ // Module system users write `@include reset.list()`.
+ @mixin list()
+ ul
+ margin: 0
+ padding: 0
+ list-style: none
+ ---
+ // _reset.import.sass
+
+ // Legacy import users can keep writing `@include reset-list()`.
+ @forward "reset" as reset-*
+<% end %>
+
+### Loading a Module That Contains Imports
+
+When you use `@use` (or `@forward`) load a module that uses `@import`, that
+module will contain all the public members defined by the stylesheet you load
+*and* everything that stylesheet transitively imports. In other words,
+everything that's imported is treated as though it were written in one big
+stylesheet.
+
+This makes it easy to convert start using `@use` in a stylesheet even before all
+the libraries you depend on have converted to the new module system. Be aware,
+though, that if they do convert their APIs may well change!
diff --git a/source/documentation/at-rules/use.html.md.erb b/source/documentation/at-rules/use.html.md.erb
new file mode 100644
index 000000000..552d9511c
--- /dev/null
+++ b/source/documentation/at-rules/use.html.md.erb
@@ -0,0 +1,9 @@
+---
+title: "@use"
+introduction: >
+ TODO(nweiz): Write this
+---
+
+### Load Paths
+
+### Partials
diff --git a/source/documentation/cli/dart-sass.html.md.erb b/source/documentation/cli/dart-sass.html.md.erb
index 820916126..11961d15b 100644
--- a/source/documentation/cli/dart-sass.html.md.erb
+++ b/source/documentation/cli/dart-sass.html.md.erb
@@ -91,11 +91,11 @@ The `--stdin` flag may not be used with [many-to-many mode][].
This flag tells Sass to parse the input file as the [indented syntax][]. If it's
used in [many-to-many mode][], all input files are parsed as the indented
-syntax, although files they [import][] will have their syntax determined as
-usual. The inverse, `--no-indented`, can be used to force all input files to be
-parsed as [SCSS][] instead.
+syntax, although files they [use][] will have their syntax determined as usual.
+The inverse, `--no-indented`, can be used to force all input files to be parsed
+as [SCSS][] instead.
-[import]: ../at-rules/import
+[use]: ../at-rules/use
The `--indented` flag is mostly useful when the input file is coming from
[standard input][], so its syntax can't be automatically determined.
@@ -110,10 +110,10 @@ h1 {
#### `--load-path`
This option (abbreviated `-I`) adds an additional [load path][] for Sass to look
-for imports. It can be passed multiple times to provide multiple load paths.
+for stylesheets. It can be passed multiple times to provide multiple load paths.
Earlier load paths will take precedence over later ones.
-[load path]: ../at-rules/import#load-paths
+[load path]: ../at-rules/use#load-paths
```shellsession
$ sass --load-path=node_modules/bootstrap/dist/css style.scss style.css
diff --git a/source/documentation/cli/migrator.html.md.erb b/source/documentation/cli/migrator.html.md.erb
new file mode 100644
index 000000000..1e429d1b3
--- /dev/null
+++ b/source/documentation/cli/migrator.html.md.erb
@@ -0,0 +1,5 @@
+---
+title: "Migrator"
+introduction: >
+ TODO(nweiz): Write this
+---
diff --git a/source/documentation/cli/ruby-sass.html.md.erb b/source/documentation/cli/ruby-sass.html.md.erb
index ce27d0c30..0de20b3f2 100644
--- a/source/documentation/cli/ruby-sass.html.md.erb
+++ b/source/documentation/cli/ruby-sass.html.md.erb
@@ -80,7 +80,7 @@ When compiling whole directories, Sass will ignore [partial files][] whose names
begin with `_`. You can use partials to separate out your stylesheets without
creating a bunch of unnecessary output files.
-[partial files]: ../at-rules/import#partials
+[partial files]: ../at-rules/use#partials
Many-to-many mode will only compile stylesheets whose dependencies have been
modified more recently than the corresponding CSS file was generated. It will
@@ -93,10 +93,10 @@ also print status messages when updating stylesheets.
#### `--load-path`
This option (abbreviated `-I`) adds an additional [load path][] for Sass to look
-for imports. It can be passed multiple times to provide multiple load paths.
+for stylesheets. It can be passed multiple times to provide multiple load paths.
Earlier load paths will take precedence over later ones.
-[load path]: ../at-rules/import#load-paths
+[load path]: ../at-rules/use#load-paths
```shellsession
$ sass --load-path=node_modules/bootstrap/dist/css style.scss style.css
diff --git a/source/documentation/js-api.html.md.erb b/source/documentation/js-api.html.md.erb
index 9441eb4f2..fd7944629 100644
--- a/source/documentation/js-api.html.md.erb
+++ b/source/documentation/js-api.html.md.erb
@@ -137,8 +137,8 @@ console.log(result.map.toString());
An array of the absolute paths of all Sass files loaded during compilation. If a
stylesheet was loaded from an [importer][] that returned the stylesheet's
-contents, the raw strings of that stylesheet's `@import` is included in this
-array.
+contents, the raw string of the `@use` or `@import` that loaded that stylesheet
+is included in this array.
[importer]: #importer
@@ -188,9 +188,9 @@ provides the same information.
The stylesheet where the error occurred. If the error occurred in a stylesheet
loaded from disk, this is the absolute path of that stylesheet. If the error
occurred in a stylesheet that was loaded from an [importer][] which returned the
-stylesheet's contents, this is the raw string of that stylesheet's `@import`. If
-it occurred in the contents of the [`data` option][], this is the string
-`"stdin"`.
+stylesheet's contents, this is the raw string of the `@use` or `@import` that
+loaded that stylesheet. If it occurred in the contents of the [`data` option][],
+this is the string `"stdin"`.
#### `error.line`
@@ -741,21 +741,23 @@ h1 {
somewhere else to break it.
<% end %>
-This option defines one or more additional handlers for loading files when an
-[`@import` rule][] is encountered. It can either be a single JavaScript
-function, or an array of functions. These functions are always passed two
-arguments:
+This option defines one or more additional handlers for loading files when a
+[`@use` rule] or an [`@import` rule][] is encountered. It can either be a single
+JavaScript function, or an array of functions. These functions are always passed
+two arguments:
+[`@use` rule]: at-rules/use
[`@import` rule]: at-rules/import
-1. The `@import` rule's URL as a string, exactly as it appears in the
+1. The `@use` or `@import` rule's URL as a string, exactly as it appears in the
stylesheet.
-2. A string identifying for the stylesheet that contained the `@import`. This
- identifier's format depends on how that stylesheet was loaded:
+2. A string identifying for the stylesheet that contained the `@use` or
+ `@import`. This identifier's format depends on how that stylesheet was
+ loaded:
* If the stylesheet was loaded from the filesystem, it's the absolute path of
its file.
* If the stylesheet was loaded from an importer that returned its contents,
- it's the URL of the `@import` rule that loaded it.
+ it's the URL of the `@use` or `@import` rule that loaded it.
* If the stylesheet came from the [`data` option][], it's the string
`"stdin"`.
@@ -775,7 +777,7 @@ asynchronously pass the result of the import once it's complete.
Imports are resolved by trying, in order:
-* Loading a file relative to the file in which the `@import` appeared.
+* Loading a file relative to the file in which the `@use` or `@import` appeared.
* Each custom importer.
@@ -793,7 +795,7 @@ sass.render({
// This importer uses the synchronous API, and can be passed to either
// renderSync() or render().
function(url, prev) {
- // This generates a stylesheet from scratch for `@import "big-headers"`.
+ // This generates a stylesheet from scratch for `@use "big-headers"`.
if (url != "big-headers") return null;
return {
@@ -807,7 +809,7 @@ h1 {
// This importer uses the asynchronous API, and can only be passed to
// render().
function(url, prev, done) {
- // Convert `@import "foo/bar"` to "node_modules/foo/sass/bar".
+ // Convert `@use "foo/bar"` to "node_modules/foo/sass/bar".
var components = url.split('/');
var innerPath = components.slice(1).join('/');
done({
diff --git a/source/documentation/snippets/_module-system-status.erb b/source/documentation/snippets/_module-system-status.erb
new file mode 100644
index 000000000..45073ecc2
--- /dev/null
+++ b/source/documentation/snippets/_module-system-status.erb
@@ -0,0 +1,6 @@
+<% impl_status dart: '(unreleased)', libsass: false, ruby: false do %>
+ Only Dart Sass currently supports `@use`. Users of other implementations must
+ use the [`@import` rule][] instead.
+
+ [`@import` rule]: /documentation/at-rules/import
+<% end %>
diff --git a/source/documentation/syntax.html.md b/source/documentation/syntax.html.md
index 2e686adcc..84540b952 100644
--- a/source/documentation/syntax.html.md
+++ b/source/documentation/syntax.html.md
@@ -1,7 +1,7 @@
---
title: Syntax
introduction: >
- Sass supports two different syntaxes. Each one can import the other, so it's
+ Sass supports two different syntaxes. Each one can load the other, so it's
up to you and your team which one to choose.
---
diff --git a/source/documentation/syntax/structure.html.md.erb b/source/documentation/syntax/structure.html.md.erb
index d5810ec46..f92361361 100644
--- a/source/documentation/syntax/structure.html.md.erb
+++ b/source/documentation/syntax/structure.html.md.erb
@@ -43,6 +43,7 @@ These statements produce CSS. They can be used anywhere except within a
These statements can only be used at the top level of a stylesheet, or nested
within a CSS statement at the top level:
+* [Module loads](../at-rules/use), using `@use`.
* [Imports](../at-rules/import), using `@import`.
* [Mixin definitions](../at-rules/mixin) using `@mixin`.
* [Function definitions](../at-rules/function) using `@function`.
diff --git a/source/documentation/variables.html.md.erb b/source/documentation/variables.html.md.erb
index bf0e2ee91..a7d53c810 100644
--- a/source/documentation/variables.html.md.erb
+++ b/source/documentation/variables.html.md.erb
@@ -88,11 +88,25 @@ use them to generate CSS.
To make this possible, Sass provides the `!default` flag. This assigns a value
to a variable *only if* that variable isn't defined or its value is [`null`][].
-Otherwise, the existing value will be used. This way, users can set variables
-before they import your library to customize its behavior.
+Otherwise, the existing value will be used.
[`null`]: values/null
+### Customizing Modules
+
+<%= partial 'snippets/module-system-status' %>
+
+Variables defined with `!default` can be customized when loading a module with
+the [`@use` rule][]. Sass libraries often use `!default` variables to allow
+their users to customize the library's CSS.
+
+[`@use` rule]: at-rules/use
+
+To load a module with customization, write `@use with (:
+, : )`. The customized values will override the
+variables' default values. Only variables written at the top level of the
+stylesheet with a `!default` flag can be customized.
+
<% example do %>
// _library.scss
$black: #000 !default;
@@ -105,10 +119,10 @@ before they import your library to customize its behavior.
}
---
// style.scss
- $black: #222;
- $border-radius: 0.1rem;
-
- @import 'library';
+ @use 'library' with (
+ $black: #222,
+ $border-radius: 0.1rem
+ );
===
// _library.sass
$black: #000 !default
@@ -120,10 +134,7 @@ before they import your library to customize its behavior.
box-shadow: $box-shadow
---
// style.sass
- $black: #222
- $border-radius: 0.1rem
-
- @import 'library'
+ @use 'library' with ($black: #222, $border-radius: 0.1rem)
===
code {
border-radius: 0.1rem;
@@ -134,10 +145,10 @@ before they import your library to customize its behavior.
## Scope
Variables declared at the top level of a stylesheet are *global*. This means
-that they can be accessed anywhere after they've been declared—even in another
-stylesheet! But that's not true for all variables. Those declared in blocks
-(curly braces in SCSS or indented code in Sass) are usually *local*, and can
-only be accessed within the block they were declared.
+that they can be accessed anywhere in their module after they've been declared.
+But that's not true for all variables. Those declared in blocks (curly braces in
+SCSS or indented code in Sass) are usually *local*, and can only be accessed
+within the block they were declared.
<% example do %>
$global-variable: global value;
diff --git a/source/guide.html.haml b/source/guide.html.haml
index 2eda441c3..3a5e1b86d 100644
--- a/source/guide.html.haml
+++ b/source/guide.html.haml
@@ -15,7 +15,7 @@ introduction: >
- [Variables](#topic-2)
- [Nesting](#topic-3)
- [Partials](#topic-4)
- - [Import](#topic-5)
+ - [Modules](#topic-5)
- [Mixins](#topic-6)
- [Inheritance](#topic-7)
- [Operators](#topic-8)
@@ -158,72 +158,72 @@ introduction: >
Sass file named with a leading underscore. You might name it something
like `_partial.scss`. The underscore lets Sass know that the file is only
a partial file and that it should not be generated into a CSS file. Sass
- partials are used with the `@import` directive.
+ partials are used with the `@use` rule.
---
%section#topic-5
- :markdown
- ## Import
+ %h2 Modules
+ = partial 'documentation/snippets/module-system-status'
- CSS has an import option that lets you split your CSS into smaller, more
- maintainable portions. The only drawback is that each time you use
- `@import` in CSS it creates another HTTP request. Sass builds on top of
- the current CSS `@import` but instead of requiring an HTTP request, Sass
- will take the file that you want to import and combine it with the file
- you're importing into so you can serve a single CSS file to the web browser.
+ :markdown
+ You don't have to write all your Sass in a single file. You can split it up
+ however you want with the `@use` rule. This rule loads another Sass file as
+ a *module*, which means you can refer to its variables, [mixins][], and
+ [functions][] in your Sass file with a namespace based on the filename.
+ Using a file will also include the CSS it generates in your compiled output!
- Let's say you have a couple of Sass files, `_reset.scss` and `base.scss`.
- We want to import `_reset.scss` into `base.scss`.
+ [mixins]: #topic-6
+ [functions]: documentation/at-rules/function
- example do
:plain
- // _reset.scss
- html,
- body,
- ul,
- ol {
- margin: 0;
- padding: 0;
+ // _base.scss
+ $font-stack: Helvetica, sans-serif;
+ $primary-color: #333;
+
+ body {
+ font: 100% $font-stack;
+ color: $primary-color;
}
---
- // base.scss
- @import 'reset';
- body {
- font: 100% Helvetica, sans-serif;
- background-color: #efefef;
+ // styles.scss
+ @use 'base';
+
+ .inverse {
+ background-color: base.$primary-color;
+ color: white;
}
===
- // _reset.sass
- html,
- body,
- ul,
- ol
- margin: 0
- padding: 0
- ---
- // base.sass
- @import reset
+ // _base.sass
+ $font-stack: Helvetica, sans-serif
+ $primary-color: #333
+
body
- font: 100% Helvetica, sans-serif
- background-color: #efefef
+ font: 100% $font-stack
+ color: $primary-color
+ ---
+ // styles.sass
+ @use 'base'
+
+ .inverse
+ background-color: base.$primary-color
+ color: white
===
- html,
- body,
- ul,
- ol {
- margin: 0;
- padding: 0;
- }
body {
font: 100% Helvetica, sans-serif;
- background-color: #efefef;
+ color: #333;
+ }
+
+ .inverse {
+ background-color: #333;
+ color: white;
}
:markdown
- Notice we're using `@import 'reset';` in the `base.scss` file. When you
- import a file you don't need to include the file extension `.scss`. Sass
- is smart and will figure it out for you.
+ Notice we're using `@use 'reset';` in the `base.scss` file. When you use a
+ file you don't need to include the file extension. Sass is smart and will
+ figure it out for you.
---