How to use a SASS $variable across multiple pages using @use?
From the Sass Lang documentation for @use
:
Members (variables, functions, and mixins) loaded with @use are only visible in the stylesheet that loads them
Think along the lines of import
in JavaScript rather than the traditional global scope of using Sass's @import
syntax.
I think you may attempting to do something like the following:
global.scss
$black: #000;
header.scss
@use "global";
.header {
color: global.$black;
}
button.scss
@use "global";
.button {
color: global.$black;
}
index.scss
@use './button';
@use './header';
This might be a bit more verbose/cumbersome than what you're traditionally accustomed to with Sass, but it certainly has tremendous benefits in the long run - especially if you're a framework or library author, or even consuming an existing one with your own modifications on top.
A big pain point with Sass that many developers (myself included) have had to deal with is variables declared at root scope and, indeed, all Sass functions are globally available. While this is convenient at times, it also leads to a large number of collisions when integrating externally-authored libraries or working in larger companies with many distributed teams.
For example: if I'm using Bootstrap as the basis of my website's style, and I load in an additional library that defines its own gradient-bg
mixin (also defined in TWBS), which mixin is the correct one to use? Load order has an impact on this, and you may not see any issues, but you may also see huge discrepancies in your expected output which now requires you to dig deep into those libraries to see what's happening.
The @use
rule solves this by ensuring that module members (variables, functions, and mixins) are only accessible inside the stylesheets that load them. It also has an added benefit of allowing you to further simplify member names - since they're scoped to a namespace (the last component of the module’s URL) you can go ahead and just define $padding
or @mixin flex {}
.
Organisation
Ultimately, this can help you to logically organise your own code into a structure that makes it easier to maintain your code going forward (for your colleagues as much as yourself). There's nothing wrong with being explicit in what your code does, especially since you want it to be reliable and predictable when you plan on making updates in the future.
Personally, I'm quite fond of a structure not dissimilar to:
styles
|-- global
| |-- functions.scss
| |-- spacing.scss
| |-- typography.scss
| |-- ...etc...
|-- component
| |-- button.scss
| |-- header.scss
| |-- ...etc...
And in a situation like this, your code would look something like:
button.scss
@use "global/spacing.scss";
@use "global/typography.scss";
.button {
font-size: typography.$standard;
padding: spacing.$standard;
}
Global namespacing
Of course, it all comes down to personal preference and I understand that some people may not be fans of the new namespacing. This can be mitigated somewhat, or ignored entirely.
With @use
When using the new Sass module system, you can't put items in the global namespace when using @use
. You can, however, load a module without a namespace by using the @use "path/to/file" as *;
syntax. This would allow you to directly access members without needing the <namespace>.<member>
syntax.
With @import
If this still doesn't suit your needs, you can of course continue to use the @import
rule for the foreseeable future. The team intend to support @import
up until some time around October 2022. At this point, you can always pin your version of Sass to the last version that supports @import
.
SASS - use variables across multiple files
This question was asked a long time ago so I thought I'd post an updated answer.
You should now avoid using @import
. Taken from the docs:
Sass will gradually phase it out over the next few years, and
eventually remove it from the language entirely. Prefer the @use rule
instead.
A full list of reasons can be found here
You should now use @use
as shown below:
_variables.scss
$text-colour: #262626;
_otherFile.scss
@use 'variables'; // Path to _variables.scss Notice how we don't include the underscore or file extension
body {
// namespace.$variable-name
// namespace is just the last component of its URL without a file extension
color: variables.$text-colour;
}
You can also create an alias for the namespace:
_otherFile.scss
@use 'variables' as v;
body {
// alias.$variable-name
color: v.$text-colour;
}
EDIT As pointed out by @und3rdg at the time of writing (November 2020) @use
is currently only available for Dart Sass and not LibSass (now deprecated) or Ruby Sass. See https://sass-lang.com/documentation/at-rules/use for the latest compatibility
Change SCSS variables from other files
You are correct in that this approach won't work. Think about how those files would be interpreted.
Example
template.scss
$background: green;
background: $background
modifier.scss
@import 'template';
$background: red;
In this case you're essentially doing:
$background: green;
background: $background
$background: red;
The end effect is background
is set to green
, and the $background
variable is redefined to red
in the end.
You would need to define background: $background
again within modifier.scss
in order for you current setup to work.
A Different Approach
One approach is to define your base styles within one file, modifier styles within another, and then set your CSS properties within a final file. Like this:
template.scss
$background: green;
modifier.scss
$background: red;
styles.scss
background: $background;
Related Topics
Is The CSS3 Transform Translate Percentage Values Relative to Its Width And/Or Height
Mobile Safari Text Input Width Bug
How to Make Entire Div Change Color on Hover Using CSS
Media Query to Target Most of Smartphone
How to Reverse-Engineer a Webkit Matrix3D Transform
Svg, Text, Font with Fixed Width/Height
How to Create Tags Like Stackoverflow with Text Styling
Why Does an Absolute Position Element Wrap Based on Its Parent's Right Bound
How to Include a CSS Stylesheet in Orchard Module
Sass Loop Through Array and Present Variable
Best Practice (Jquery, CSS): How to Initialize Hidden Elements That Will Toggle Visible
CSS: Opacity Only Background, Not The Text Inside
React Testing Library (Rtl): Test a Responsive Design
Does a CSS3 Animation Run When Parent Element Has Visibility: Hidden
Borderradius Style Property Not Rounding The Edges in Reactjs
Does Pattern Lab "Not Mix Well" with Angular
What Is The Biggest Usable Number for Use in Calc() in CSS
How to Render a Border to a Div Without Occupying Any Extra Space