Traditionally, any variable declared outside of a selector in Scss has a global scope, and variables declared inside of a selector have a local scope:
$global-variable: 10px;
.some-class {
$local-variable: 5px;
}
Global variables can cause problems in large projects because you can accidentally overwrite them from any file.
For example, let's say you had a variable called $grid-gutter-width
with a value of 16px
in a _variables.scss
file. You could accidentally override that variable in another file:
// _some-other-file.scss
$grid-gutter-width: 40px;
.fancy-column {
padding-left: $grid-gutter-width * 0.5;
padding-right: $grid-gutter-width * 0.5;
}
.fancy-row {
margin-left: $grid-gutter-width * -0.5;
margin-right: $grid-gutter-width * -0.5;
}
This would overwrite the $grid-gutter-width
variable for every subsequent use, setting the value to 40px
instead of 16px
. Something like this could potentially break the entire layout of the site.
While new versions of Scss prevent global scoping by using the @use rule, LibSass-based versions of Scss like node-sass
and Hugo's Scss don't support this feature.
Limiting the scope using @at-root
So how can you scope a variable to a single file in older versions of Scss? You can wrap the file in an @at-root
rule:
@at-root {
$grid-gutter-width: 40px;
.fancy-column {
padding-left: $grid-gutter-width * 0.5;
padding-right: $grid-gutter-width * 0.5;
}
.fancy-row {
margin-left: $grid-gutter-width * -0.5;
margin-right: $grid-gutter-width * -0.5;
}
}
The @at-root rule in Scss causes everything within it to be emitted at the root of the document instead of using the normal nesting. It's typically used to escape from a nested context, but in the example above we can use it to enclose a new local scope.
By setting the$grid-gutter-width
variable within the @at-root
block, we can overwrite its value in that file without overwriting it elsewhere in your stylesheet.
Top comments (0)