How to use a SASS $variable across multiple pages using #use? - css

I am trying to use a variable that was declared on one partial inside of another partial, both of which will be loaded into the main.scss file using #use, which will then be compiled into css.
Here's the setup:
style.scss
#use './global';
#use './header';
_global.scss
$black: #262626;
_header.scss
header {
color: $black
}
When I run try to compile style.css, I get this error:
C:\xampp\htdocs\Site\styles>sass style.scss:style.css
Error: Undefined variable.
╷
3 │ color: $black;
│ ^^^^^^
╵
_header.scss 3:10 #use
style.scss 2:1 root stylesheet
It works fine if I use #import instead of #use in my main style.scss, but the developers of Sass advise not to use #import because it is going to be deprecated eventually.
They say to use #use instead, and that #use has many advantages over #import, one of which being that all instances of #use can be loaded at the same time. I think this is what's causing the issue, since _global.scss doesn't get to load before the pages which rely on $black defined in _global.scss, so those pages load without $black defined.
Any ideas?

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.

Hello Guys!!
So I've been researching on how to use my SCSS variable in my index style across other style file in my code and I finally figured it out : ). Kindly follow this step carefully and trust me you would get it figured out also
1. Have a index or main file where all your variables are declared in just like this (for me, my file name was "index.scss"
2. After step one is completed now go to any other style file you want to add the variables to. (for me i had a file called "register.scss")
3. import the file where you declared all your scss variable (mine was "index.scss") and do not include the "scss" extension see sample below
NB: You can decide to import it as an alias or without any, if you don't import it as an alias (for me i imported it as 'v') you would have to use the "file_name.variable_name" to use the variable in other file. so as for me i just used "v.$variable_name" since i imported the file as an alias "v".
Boom! You done
I hope this post really helps you! Enjoy and happy coding! : )

Related

Why are my Sass variables shown as not defined upon compilation?

I'm trying to set up a project with Sass, and even though I have already made multiple Sass projects and everything seemed to work just fine, now I'm not able to use Sass (SCSS) variables at all. I checked and re-checked all of the syntax multiple times, however I can't seem to find the solution. I use dart-sass, but in the SCSS formatting.
My file structure:
styles
css
style.css
style.css.map
scss
components
_components.scss (uses #forward to import the rest of the files)
globals
_globals.scss (uses #forward to import the rest of the files)
basics.scss
colors.scss (the color variables that I'm talking about are declared here)
fonts.scss
typography.scss
util
_util.scss (uses #forward to import the rest of the files)
functions.scss
style.scss (uses #use to import the rest of the partial indexes)
My syntax for declaring variables and then calling them should be alright:
Declaring (in colors.scss):
$blue-300: hsl(204, 100%, 45%);
Then calling them (e.g. in _globals.scss):
h1 {color: $blue-300;}
I suspect it has something to do with the scope of the documents and their locations in individual folders, but I still can't wrap my head around it.
Thanks in advance
By defaut #use and #forward namespace their variables (see this). Try #forward *file* as * and #use globals/globals as *. This will remove the namespace. If you do want the namespace, try globals.colors.$blue-300.
also can you tell the version of sass you're using? (sass --version)

How to fix an Undefined Variable Error in SCSS?

I've run into an Undefined Variable Error writing SCSS.
My file structure is sound (I believe), because it compiles the rest of the files as it should into main.scss.
I'm using #use instead of #import.
color: #f22437 vs color: $clr-primary
Error: Undefined variable.
╷
54 │ color: $clr-primary;
│ ^^^^^^^^^^^^
╵
scss/layouts/_navigation.scss 54:10 #use
scss/layouts/_all-layouts.scss 11:1 #use
scss/main.scss 7:1 root stylesheet
The files that are in question.
File Structure
UPDATE I changed all #use to #import, and it worked.
Please me understand why this worked and how I can #use instead of #import. Seems like an issue related to SASS, but I could still be at fault. For now I'll 'hack' it.
I had the same issue and after reading the docs, they say this:
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.
Solutions:
Preferred solution: Use #use in the styles file that is going to use the variables and not in the global one and call the variable like:
namespace.variablename
Use the forward rule as docs say
Use #import instead of #use but according to this, "Sass will gradually phase it out over the next few years, and eventually remove it from the language entirely"
First:
#use is currently only available for Dart Sass and not LibSass or Ruby Sass. See https://sass-lang.com/documentation/at-rules/use for the latest compatibility
Second:
_variables.scss
$text-colour: #262626;
_otherFile.scss
#use 'variables';
body {
color: variables.$text-colour;
}
Check #whiscode answer here: https://stackoverflow.com/a/61500282/2470685
This works for me
`#use 'variables';
body {
color: variables.$text-colour;
}`

Accessing custom properties in SASS modules

So, let's say I have a SASS module _module.scss that declares some css variables aka custom properties. When I now load this module in another SASS styleshee, let's call it main.scss, I have access to all SASS-variables, mixins and also rules, but not the custom properties inside of it? Am I missing something?
Example files:
//_module.scss
:root {
--some-variable: red;
}
// main.scss
#use 'module';
div {
background-color: var(module.--some-variable); // won't work, private property because of leading '-'
background-color: module.var(--some-variable); // won't work, would have been horrible syntax as well
}
I could use #import but that is discouraged and deprecated (see SASS Documentation). I've tried including the variables in a pure css file module.css, which compiled but didn't declare any custom properties at runtime as it directly translates the #use 'module' from my SASS file to the exact same in CSS - which browsers don't understand obviously. It should just more or less copy the content of a pure css file but it doesn't. Sure, I could try writing mixins in my modules that set the variables but that's just a workaround.
Am I missing something? Do I really need to write a mixin, that sets the variables and needs to be loaded? This makes the use of custom properties within modules pretty cumbersome.
EDIT
Forgot to mention, that background-color: var(--some-variable) doesn't work either even though it should according to the documentation, since rules should just be applied directly without scoping.
Ugh. The issue is most definitely the fact that my VS Code extension uses LibSass and not Dart Sass. Therefore #use is not yet supported in most environments. The documentation should most definitely be more explicit about this especially when warning about the use of #import.
Since I know it works with #import the issue is resolved though I'd love to see the module system being included in LibSass as well.
tl;dr
Do no use #use if you're not absolutely certain that you use Dart Sass!

How can I import a .scss module within my main.scss with #use

So, let's assume I have the following situation: I have 2 .scss files.
One with a variable, and one that will be actually translated into .css for my webpage, where I want to access to said variable.
vars.scss
$my_color: red;
main.scss
#use 'vars'
body {
color: $my_color;
}
What I am trying to do is to access the variable defined in vars.css and use it.
The reference is correct since if I use #import instead of #use, everything works
I've also tried to reference to the variable with vars.$my_color as was suggested in the documentation, but I keep getting a "undefined variable" error.
Well, if you read the documentation then in the ⚠️ Heads up! section, where the undesirability of further use of the #import rule is written, below, you can read the following:
The #import rule has a number of serious problems:
#import makes all variables, mixins, and functions globally available.
Therefore, the #use rule makes them inaccessible. Which is what you observe in action.
I think to achieve the desired result, combination of #use and #forward rules should be used.
But I am using VSCode Live Sass Compiler (Maybe you're using it too?) where #use is not supported so I couldn't give you the exact howto.
Hope this clarifies a lot.

Sass importing without compiling

In sass, the way one imports is by using the import command. I will use Zurb Foundation as an example:
#import "foundation";
This will then import the whole foundation.scss file and all it's relative imports to the top of the current file. This means that the entire foundation.scss file will be compiled and outputted along with the contents of the file to the final <name here>.css file.
Though this is good for customisation, such as custom colors and spacing, it becomes a pain when creating libraries and distributing these libraries as individual droplets for other people to slot into their existing projects.
Is there a way to import files as "references", so that mixins and other variables become available in the scope of the current file, but other css statements are ignored? The LESS css preprocessor has a newly implemented import tag similar to this (appropriately named a reference).
Taking a look at Foundation demonstrates a good approach to this:
https://github.com/zurb/bower-foundation/blob/master/scss/foundation/components/_breadcrumbs.scss
Here they have one #import "global"; at the top of the file.
That is followed by a bunch of mixins
At the bottom they have:
#include exports("breadcrumbs") {
#if $include-html-nav-classes {
.breadcrumbs {
#include crumb-container;
#include radius($crumb-radius);
&>* {
#include crumbs;
}
}
}
}
The $include-html-nav-classes is set to true by default in the _global.scss file. It can be overridden in any other file by changing it to false. This allows you to both use the mixins and generate html.
If you don't need to generate any css just include mixins only and it will simplify your situation. I believe that they do this to allow for fast customization and optimization of the outputted css.

Resources