sass-site/source/documentation/at-rules/use.liquid

615 lines
15 KiB
Plaintext
Raw Normal View History

---
title: "@use"
table_of_contents: true
eleventyComputed:
2023-05-25 21:02:28 +02:00
before_introduction: >
{% render 'documentation/snippets/module-system-status' %}
introduction: >
2023-05-25 21:02:28 +02:00
The `@use` rule loads [mixins](/documentation/at-rules/mixin),
[functions](/documentation/at-rules/function), and
[variables](/documentation/variables) from other Sass stylesheets, and
combines CSS from multiple stylesheets together. Stylesheets loaded by `@use`
are called "modules". Sass also provides [built-in
modules](/documentation/modules) full of useful functions.
---
2023-05-25 21:02:28 +02:00
{% markdown %}
2023-05-30 23:23:34 +02:00
The simplest `@use` rule is written `@use "<url>"`, which loads the module at
the given URL. Any styles loaded this way will be included exactly once in the
compiled CSS output, no matter how many times those styles are loaded.
{% endmarkdown %}
{% headsUp %}
2023-05-30 23:23:34 +02:00
A stylesheet's `@use` rules must come before any rules other than `@forward`,
including [style rules][]. However, you can declare variables before `@use`
rules to use when [configuring modules][].
2023-05-30 23:23:34 +02:00
[style rules]: /documentation/style-rules
[configuring modules]: #configuration
{% endheadsUp %}
{% codeExample 'use' %}
2023-05-30 23:23:34 +02:00
// foundation/_code.scss
code {
padding: .25em;
line-height: 0;
}
---
// foundation/_lists.scss
ul, ol {
text-align: left;
& & {
padding: {
bottom: 0;
left: 0;
}
}
}
2023-05-30 23:23:34 +02:00
---
// style.scss
@use 'foundation/code';
@use 'foundation/lists';
===
// foundation/_code.sass
code
padding: .25em
line-height: 0
---
// foundation/_lists.sass
ul, ol
text-align: left
& &
padding:
bottom: 0
left: 0
---
// style.sass
@use 'foundation/code'
@use 'foundation/lists'
===
code {
padding: .25em;
line-height: 0;
}
ul, ol {
text-align: left;
}
ul ul, ol ol {
padding-bottom: 0;
padding-left: 0;
}
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
## Loading Members
2023-05-30 23:23:34 +02:00
You can access variables, functions, and mixins from another module by writing
`<namespace>.<variable>`, `<namespace>.<function>()`, or `@include
<namespace>.<mixin>()`. By default, the namespace is just the last component
of the module's URL.
2023-05-30 23:23:34 +02:00
Members (variables, functions, and mixins) loaded with `@use` are only visible
in the stylesheet that loads them. Other stylesheets will need to write their
own `@use` rules if they also want to access them. This helps make it easy to
figure out exactly where each member is coming from. If you want to load
members from many files at once, you can use the [`@forward` rule][] to
forward them all from one shared file.
2023-05-30 23:23:34 +02:00
[`@forward` rule]: /documentation/at-rules/forward
2023-05-25 21:02:28 +02:00
{% endmarkdown %}
{% funFact %}
2023-05-30 23:23:34 +02:00
Because `@use` adds namespaces to member names, it's safe to choose very
simple names like `$radius` or `$width` when writing a stylesheet. This is
different from the old [`@import` rule][], which encouraged that users write
long names like `$mat-corner-radius` to avoid conflicts with other libraries,
and it helps keep your stylesheets clear and easy to read!
2023-05-30 23:23:34 +02:00
[`@import` rule]: /documentation/at-rules/import
{% endfunFact %}
{% codeExample 'loading-members' %}
2023-05-30 23:23:34 +02:00
// src/_corners.scss
$radius: 3px;
2023-05-30 23:23:34 +02:00
@mixin rounded {
border-radius: $radius;
}
---
// style.scss
@use "src/corners";
.button {
@include corners.rounded;
padding: 5px + corners.$radius;
}
===
// src/_corners.sass
$radius: 3px
@mixin rounded
border-radius: $radius
---
// style.sass
@use "src/corners"
.button
@include corners.rounded
padding: 5px + corners.$radius
===
.button {
border-radius: 3px;
padding: 8px;
}
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
### Choosing a Namespace
2023-05-30 23:23:34 +02:00
By default, a module's namespace is just the last component of its URL without
a file extension. However, sometimes you might want to choose a different
namespace—you might want to use a shorter name for a module you refer to a
lot, or you might be loading multiple modules with the same filename. You can
do this by writing `@use "<url>" as <namespace>`.
{% endmarkdown %}
{% codeExample 'namespace' %}
2023-05-30 23:23:34 +02:00
// src/_corners.scss
$radius: 3px;
2023-05-30 23:23:34 +02:00
@mixin rounded {
border-radius: $radius;
}
---
// style.scss
@use "src/corners" as c;
.button {
@include c.rounded;
padding: 5px + c.$radius;
}
===
// src/_corners.sass
$radius: 3px
@mixin rounded
border-radius: $radius
---
// style.sass
@use "src/corners" as c
.button
@include c.rounded
padding: 5px + c.$radius
===
.button {
border-radius: 3px;
padding: 8px;
}
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
You can even load a module *without* a namespace by writing `@use "<url>" as
*`. We recommend you only do this for stylesheets written by you, though;
otherwise, they may introduce new members that cause name conflicts!
{% endmarkdown %}
2023-05-25 21:02:28 +02:00
{% codeExample 'use-url' %}
2023-05-30 23:23:34 +02:00
// src/_corners.scss
$radius: 3px;
2023-05-30 23:23:34 +02:00
@mixin rounded {
border-radius: $radius;
}
---
// style.scss
@use "src/corners" as *;
.button {
@include rounded;
padding: 5px + $radius;
}
===
// src/_corners.sass
$radius: 3px
@mixin rounded
border-radius: $radius
---
// style.sass
@use "src/corners" as *
.button
@include rounded
padding: 5px + $radius
===
.button {
border-radius: 3px;
padding: 8px;
}
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
### Private Members
As a stylesheet author, you may not want all the members you define to be
available outside your stylesheet. Sass makes it easy to define a private
member by starting its name with either `-` or `_`. These members will work
just like normal within the stylesheet that defines them, but they won't be
part of a module's public API. That means stylesheets that load your module
can't see them!
{% endmarkdown %}
{% funFact %}
2023-05-30 23:23:34 +02:00
If you want to make a member private to an entire *package* rather than just a
single module, just don't [forward its module][] from any of your package's
entrypoints (the stylesheets you tell your users to load to use your package).
You can even [hide that member][] while forwarding the rest of its module!
2023-05-30 23:23:34 +02:00
[forward its module]: /documentation/at-rules/forward
[hide that member]: /documentation/at-rules/forward#controlling-visibility
{% endfunFact %}
2023-05-25 21:02:28 +02:00
{% codeExample 'private-members', false %}
2023-05-30 23:23:34 +02:00
// src/_corners.scss
$-radius: 3px;
2023-05-30 23:23:34 +02:00
@mixin rounded {
border-radius: $-radius;
}
---
// style.scss
@use "src/corners";
2023-05-30 23:23:34 +02:00
.button {
@include corners.rounded;
2023-05-30 23:23:34 +02:00
// This is an error! $-radius isn't visible outside of `_corners.scss`.
padding: 5px + corners.$-radius;
}
===
// src/_corners.sass
$-radius: 3px
2023-05-30 23:23:34 +02:00
@mixin rounded
border-radius: $-radius
---
// style.sass
@use "src/corners"
2023-05-30 23:23:34 +02:00
.button
@include corners.rounded
2023-05-30 23:23:34 +02:00
// This is an error! $-radius isn't visible outside of `_corners.scss`.
padding: 5px + corners.$-radius
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
## Configuration
2023-05-30 23:23:34 +02:00
A stylesheet can define variables with the [`!default` flag][] to make them
configurable. To load a module with configuration, write `@use <url> with
(<variable>: <value>, <variable>: <value>)`. The configured values will
override the variables' default values.
2023-05-30 23:23:34 +02:00
[`!default` flag]: /documentation/variables#default-values
{% endmarkdown %}
{% render 'code-snippets/example-use-with' %}
{% markdown %}
2023-05-30 23:23:34 +02:00
### With Mixins
Configuring modules with `@use ... with` can be very handy, especially when
using libraries that were originally written to work with the [`@import`
rule][]. But it's not particularly flexible, and we don't recommend it for
more advanced use-cases. If you find yourself wanting to configure many
variables at once, pass [maps][] as configuration, or update the configuration
after the module is loaded, consider writing a mixin to set your variables
instead and another mixin to inject your styles.
[`@import` rule]: /documentation/at-rules/import
[maps]: /documentation/values/maps
{% endmarkdown %}
{% codeExample 'with-mixins' %}
2023-05-30 23:23:34 +02:00
// _library.scss
$-black: #000;
$-border-radius: 0.25rem;
$-box-shadow: null;
/// If the user has configured `$-box-shadow`, returns their configured value.
/// Otherwise returns a value derived from `$-black`.
@function -box-shadow() {
@return $-box-shadow or (0 0.5rem 1rem rgba($-black, 0.15));
}
2023-05-30 23:23:34 +02:00
@mixin configure($black: null, $border-radius: null, $box-shadow: null) {
@if $black {
$-black: $black !global;
}
@if $border-radius {
$-border-radius: $border-radius !global;
}
@if $box-shadow {
$-box-shadow: $box-shadow !global;
}
}
2023-05-30 23:23:34 +02:00
@mixin styles {
code {
border-radius: $-border-radius;
box-shadow: -box-shadow();
}
}
---
// style.scss
@use 'library';
@include library.configure(
$black: #222,
$border-radius: 0.1rem
);
@include library.styles;
===
// _library.sass
$-black: #000
$-border-radius: 0.25rem
$-box-shadow: null
/// If the user has configured `$-box-shadow`, returns their configured value.
/// Otherwise returns a value derived from `$-black`.
@function -box-shadow()
@return $-box-shadow or (0 0.5rem 1rem rgba($-black, 0.15))
@mixin configure($black: null, $border-radius: null, $box-shadow: null)
@if $black
$-black: $black !global
@if $border-radius
$-border-radius: $border-radius !global
@if $box-shadow
$-box-shadow: $box-shadow !global
@mixin styles
code
border-radius: $-border-radius
box-shadow: -box-shadow()
---
// style.sass
@use 'library'
@include library.configure($black: #222, $border-radius: 0.1rem)
@include library.styles
===
code {
2023-05-30 23:23:34 +02:00
border-radius: 0.1rem;
box-shadow: 0 0.5rem 1rem rgba(34, 34, 34, 0.15);
}
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
### Reassigning Variables
2023-05-30 23:23:34 +02:00
After loading a module, you can reassign its variables.
{% endmarkdown %}
2023-05-25 21:02:28 +02:00
{% codeExample 'reassigning-variables', false %}
2023-05-30 23:23:34 +02:00
// _library.scss
$color: red;
---
// _override.scss
@use 'library';
library.$color: blue;
---
// style.scss
@use 'library';
@use 'override';
@debug library.$color; //=> blue
===
// _library.sass
$color: red
---
// _override.sass
@use 'library'
library.$color: blue
---
// style.sass
@use 'library'
@use 'override'
@debug library.$color //=> blue
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
This even works if you import a module without a namespace using `as *`.
Assigning to a variable name defined in that module will overwrite its value
in that module.
2023-05-25 21:02:28 +02:00
{% endmarkdown %}
{% headsUp %}
2023-05-30 23:23:34 +02:00
Built-in module variables (such as [`math.$pi`]) cannot be reassigned.
2023-05-30 23:23:34 +02:00
[`math.$pi`]: /documentation/modules/math#$pi
{% endheadsUp %}
2023-05-25 21:02:28 +02:00
{% markdown %}
2023-05-30 23:23:34 +02:00
## Finding the Module
2023-05-30 23:23:34 +02:00
It wouldn't be any fun to write out absolute URLs for every stylesheet you
load, so Sass's algorithm for finding a module makes it a little easier. For
starters, you don't have to explicitly write out the extension of the file you
want to load; `@use "variables"` will automatically load `variables.scss`,
`variables.sass`, or `variables.css`.
2023-05-25 21:02:28 +02:00
{% endmarkdown %}
{% headsUp %}
2023-05-30 23:23:34 +02:00
To ensure that stylesheets work on every operating system, Sass loads files by
*URL*, not by *file path*. This means you need to use forward slashes, not
backslashes, even on Windows.
{% endheadsUp %}
2023-05-25 21:02:28 +02:00
{% markdown %}
2023-05-30 23:23:34 +02:00
### Load Paths
2023-05-30 23:23:34 +02:00
All Sass implementations allow users to provide *load paths*: paths on the
filesystem that Sass will look in when locating modules. For example, if you
pass `node_modules/susy/sass` as a load path, you can use `@use "susy"` to
load `node_modules/susy/sass/susy.scss`.
2023-05-30 23:23:34 +02:00
Modules will always be loaded relative to the current file first, though. Load
paths will only be used if no relative file exists that matches the module's
URL. This ensures that you can't accidentally mess up your relative imports
when you add a new library.
2023-05-25 21:02:28 +02:00
{% endmarkdown %}
{% funFact %}
2023-05-30 23:23:34 +02:00
Unlike some other languages, Sass doesn't require that you use `./` for
relative imports. Relative imports are always available.
{% endfunFact %}
2023-05-25 21:02:28 +02:00
{% markdown %}
2023-05-30 23:23:34 +02:00
### Partials
2023-05-30 23:23:34 +02:00
As a convention, Sass files that are only meant to be loaded as modules, not
compiled on their own, begin with `_` (as in `_code.scss`). These are called
*partials*, and they tell Sass tools not to try to compile those files on
their own. You can leave off the `_` when importing a partial.
2023-05-30 23:23:34 +02:00
### Index Files
2023-05-30 23:23:34 +02:00
If you write an `_index.scss` or `_index.sass` in a folder, the index file
will be loaded automatically when you load the URL for the folder itself.
{% endmarkdown %}
{% codeExample 'index-files' %}
2023-05-30 23:23:34 +02:00
// foundation/_code.scss
code {
padding: .25em;
line-height: 0;
}
---
// foundation/_lists.scss
ul, ol {
text-align: left;
& & {
padding: {
bottom: 0;
left: 0;
}
}
}
2023-05-30 23:23:34 +02:00
---
// foundation/_index.scss
@use 'code';
@use 'lists';
---
// style.scss
@use 'foundation';
===
// foundation/_code.sass
code
padding: .25em
line-height: 0
---
// foundation/_lists.sass
ul, ol
text-align: left
& &
padding:
bottom: 0
left: 0
---
// foundation/_index.sass
@use 'code'
@use 'lists'
---
// style.sass
@use 'foundation'
===
code {
padding: .25em;
line-height: 0;
}
ul, ol {
text-align: left;
}
ul ul, ol ol {
padding-bottom: 0;
padding-left: 0;
}
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
## Loading CSS
2023-05-30 23:23:34 +02:00
In addition to loading `.sass` and `.scss` files, Sass can load plain old
`.css` files.
{% endmarkdown %}
{% codeExample 'loading-css' %}
2023-05-30 23:23:34 +02:00
// code.css
code {
padding: .25em;
line-height: 0;
}
---
// style.scss
@use 'code';
===
// code.css
code {
padding: .25em;
line-height: 0;
}
---
// style.sass
@use 'code'
===
code {
padding: .25em;
line-height: 0;
}
{% endcodeExample %}
{% markdown %}
2023-05-30 23:23:34 +02:00
CSS files loaded as modules don't allow any special Sass features and so can't
expose any Sass variables, functions, or mixins. In order to make sure authors
don't accidentally write Sass in their CSS, all Sass features that aren't also
valid CSS will produce errors. Otherwise, the CSS will be rendered as-is. It
can even be [extended][]!
2023-05-30 23:23:34 +02:00
[extended]: /documentation/at-rules/extend
2023-05-30 23:23:34 +02:00
## Differences From `@import`
2023-05-30 23:23:34 +02:00
The `@use` rule is intended to replace the old [`@import` rule], but it's
intentionally designed to work differently. Here are some major differences
between the two:
2023-05-30 23:23:34 +02:00
* `@use` only makes variables, functions, and mixins available within the scope
of the current file. It never adds them to the global scope. This makes it
easy to figure out where each name your Sass file references comes from, and
means you can use shorter names without any risk of collision.
2023-05-30 23:23:34 +02:00
* `@use` only ever loads each file once. This ensures you don't end up
accidentally duplicating your dependencies' CSS many times over.
2023-05-30 23:23:34 +02:00
* `@use` must appear at the beginning your file, and cannot be nested in style
rules.
2023-05-30 23:23:34 +02:00
* Each `@use` rule can only have one URL.
2023-05-30 23:23:34 +02:00
* `@use` requires quotes around its URL, even when using the [indented
syntax].
2023-05-30 23:23:34 +02:00
[`@import` rule]: /documentation/at-rules/import
[indented syntax]: /documentation/syntax#the-indented-syntax
{% endmarkdown %}