sass-site/source/documentation/variables.liquid
Jonny Gerig Meyer 7ec5fe1201
review
2023-05-25 15:02:28 -04:00

358 lines
9.6 KiB
Plaintext

---
title: Variables
table_of_contents: true
introduction: >
Sass variables are simple: you assign a value to a name that begins with `$`,
and then you can refer to that name instead of the value itself. But despite
their simplicity, they're one of the most useful tools Sass brings to the
table. Variables make it possible to reduce repetition, do complex math,
configure libraries, and much more.
---
{% markdown %}
A variable declaration looks a lot like a [property declaration][]: it's written
`<variable>: <expression>`. Unlike a property, which can only be declared in a
style rule or at-rule, variables can be declared anywhere you want. To use a
variable, just include it in a value.
[property declaration]: /documentation/style-rules/declarations
{% endmarkdown %}
{% codeExample 'variable' %}
$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);
.alert {
border: 1px solid $border-dark;
}
===
$base-color: #c6538c
$border-dark: rgba($base-color, 0.88)
.alert
border: 1px solid $border-dark
{% endcodeExample %}
{% headsUp false %}
{% markdown %}
CSS has [variables of its own][], which are totally different than Sass
variables. Know the differences!
[variables of its own]: /documentation/style-rules/declarations#custom-properties
* Sass variables are all compiled away by Sass. CSS variables are included in
the CSS output.
* CSS variables can have different values for different elements, but Sass
variables only have one value at a time.
* Sass variables are *imperative*, which means if you use a variable and then
change its value, the earlier use will stay the same. CSS variables are
*declarative*, which means if you change the value, it'll affect both earlier
uses and later uses.
{% endmarkdown %}
{% codeExample 'variable-heads-up' %}
$variable: value 1;
.rule-1 {
value: $variable;
}
$variable: value 2;
.rule-2 {
value: $variable;
}
===
$variable: value 1
.rule-1
value: $variable
$variable: value 2
.rule-2
value: $variable
{% endcodeExample %}
{% endheadsUp %}
{% funFact %}
Sass variables, like all Sass identifiers, treat hyphens and underscores as
identical. This means that `$font-size` and `$font_size` both refer to the same
variable. This is a historical holdover from the very early days of Sass, when
it *only* allowed underscores in identifier names. Once Sass added support for
hyphens to match CSS's syntax, the two were made equivalent to make migration
easier.
{% endfunFact %}
{% markdown %}
## Default Values
Normally when you assign a value to a variable, if that variable already had a
value, its old value is overwritten. But if you're writing a Sass library, you
might want to allow your users to configure your library's variables before you
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.
[`null`]: /documentation/values/null
{% endmarkdown %}
{{ '### Configuring Modules' | markdown }}
{% render 'documentation/snippets/module-system-status' %}
{% markdown %}
Variables defined with `!default` can be configured when loading a module with
the [`@use` rule][]. Sass libraries often use `!default` variables to allow
their users to configure the library's CSS.
[`@use` rule]: /documentation/at-rules/use
To load a module with configuration, write `@use <url> with (<variable>:
<value>, <variable>: <value>)`. The configured values will override the
variables' default values. Only variables written at the top level of the
stylesheet with a `!default` flag can be configured.
{% endmarkdown %}
{% render 'code-snippets/example-use-with' %}
{% markdown %}
## Built-in Variables
Variables that are defined by a [built-in module] cannot be modified.
[built-in module]: /documentation/modules
{% endmarkdown %}
{% codeExample 'built-in-variables', false %}
@use "sass:math" as math;
// This assignment will fail.
math.$pi: 0;
===
@use "sass:math" as math
// This assignment will fail.
math.$pi: 0
{% endcodeExample %}
{% markdown %}
## Scope
Variables declared at the top level of a stylesheet are *global*. This means
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.
{% endmarkdown %}
{% codeExample 'scope' %}
$global-variable: global value;
.content {
$local-variable: local value;
global: $global-variable;
local: $local-variable;
}
.sidebar {
global: $global-variable;
// This would fail, because $local-variable isn't in scope:
// local: $local-variable;
}
===
$global-variable: global value
.content
$local-variable: local value
global: $global-variable
local: $local-variable
.sidebar
global: $global-variable
// This would fail, because $local-variable isn't in scope:
// local: $local-variable
{% endcodeExample %}
{% markdown %}
### Shadowing
Local variables can even be declared with the same name as a global variable. If
this happens, there are actually two different variables with the same name: one
local and one global. This helps ensure that an author writing a local variable
doesn't accidentally change the value of a global variable they aren't even
aware of.
{% endmarkdown %}
{% codeExample 'shadowing' %}
$variable: global value;
.content {
$variable: local value;
value: $variable;
}
.sidebar {
value: $variable;
}
===
$variable: global value
.content
$variable: local value
value: $variable
.sidebar
value: $variable
{% endcodeExample %}
{% markdown %}
If you need to set a global variable's value from within a local scope (such as
in a mixin), you can use the `!global` flag. A variable declaration flagged as
`!global` will *always* assign to the global scope.
{% endmarkdown %}
{% codeExample 'global-variable' %}
$variable: first global value;
.content {
$variable: second global value !global;
value: $variable;
}
.sidebar {
value: $variable;
}
===
$variable: first global value
.content
$variable: second global value !global
value: $variable
.sidebar
value: $variable
{% endcodeExample %}
{% headsUp false %}
{% # Arguments are (in order): `dart`, `libsass`, `node`, `ruby`, optional feature name, additional details within %}
{% compatibility "2.0.0", false, null, false %}
Older Sass versions allowed `!global` to be used for a variable that doesn't
exist yet. This behavior was deprecated to make sure each stylesheet declares
the same variables no matter how it's executed.
{% endcompatibility %}
{% markdown %}
The `!global` flag may only be used to set a variable that has already been
declared at the top level of a file. It *may not* be used to declare a new
variable.
{% endmarkdown %}
{% endheadsUp %}
{% markdown %}
### Flow Control Scope
Variables declared in [flow control rules][] have special scoping rules: they
don't shadow variables at the same level as the flow control rule. Instead, they
just assign to those variables. This makes it much easier to conditionally
assign a value to a variable, or build up a value as part of a loop.
[flow control rules]: /documentation/at-rules/control
{% endmarkdown %}
{% codeExample 'flow-control' %}
$dark-theme: true !default;
$primary-color: #f8bbd0 !default;
$accent-color: #6a1b9a !default;
@if $dark-theme {
$primary-color: darken($primary-color, 60%);
$accent-color: lighten($accent-color, 60%);
}
.button {
background-color: $primary-color;
border: 1px solid $accent-color;
border-radius: 3px;
}
===
$dark-theme: true !default
$primary-color: #f8bbd0 !default
$accent-color: #6a1b9a !default
@if $dark-theme
$primary-color: darken($primary-color, 60%)
$accent-color: lighten($accent-color, 60%)
.button
background-color: $primary-color
border: 1px solid $accent-color
border-radius: 3px
{% endcodeExample %}
{% headsUp %}
Variables in flow control scope can assign to existing variables in the outer
scope, but new variables declared in flow control scope won't be accessible in
the outer scope. Make sure the variable is already declared before you assign to
it, even if you need to declare it as `null`.
{% endheadsUp %}
{% markdown %}
## Advanced Variable Functions
The Sass core library provides a couple advanced functions for working with
variables. The [`meta.variable-exists()` function][] returns whether a variable
with the given name exists in the current scope, and the
[`meta.global-variable-exists()` function][] does the same but only for the
global scope.
[`meta.variable-exists()` function]: /documentation/modules/meta#variable-exists
[`meta.global-variable-exists()` function]: /documentation/modules/meta#global-variable-exists
{% endmarkdown %}
{% headsUp false %}
{% markdown %}
Users occasionally want to use interpolation to define a variable name based on
another variable. Sass doesn't allow this, because it makes it much harder to
tell at a glance which variables are defined where. What you *can* do, though,
is define a [map][] from names to values that you can then access using
variables.
[map]: /documentation/values/maps
{% endmarkdown %}
{% codeExample 'advanced-variable-functions' %}
@use "sass:map";
$theme-colors: (
"success": #28a745,
"info": #17a2b8,
"warning": #ffc107,
);
.alert {
// Instead of $theme-color-#{warning}
background-color: map.get($theme-colors, "warning");
}
===
@use "sass:map"
$theme-colors: ("success": #28a745, "info": #17a2b8, "warning": #ffc107)
.alert
// Instead of $theme-color-#{warning}
background-color: map.get($theme-colors, "warning")
===
.alert {
background-color: #ffc107;
}
{% endcodeExample %}
{% endheadsUp %}