Variables are global with SASS but not SCSS - css

I have my application.css.scss set like this:
#import "base/variables";
#import "./application/application";
Like the documentation says I am not using Sprockets' directives (require, require_tree, and require_self) at all so I expect my variables defined inside of base/_variables.scss to be globals and available for my /application/application.scss file but it's not the case:
#content {
margin-top: $big;
}
Will return the error Undefined variable: "$big".
I've tried the same thing with SASS by naming by files application.css.sass and /application/application.sass and while the variables now do seems to be globals I'll like to keep using the SCSS syntax, I've tried that by setting config.sass.preferred_syntax = :scss but I'm still being asked for Sass.
Of course I could just import my variables file everytime I need my variables but that would go against the DRY principle.
Is that possible to use the SCSS syntax while making my variables globally available? What am I missing here? Thanks in advance.

What versions of sprockets, rails and sass-rails gems do you have? There were some problems around undefined variables, maybe try to bump up sass-rails and sprockets (if possible).

My application/application.scss was being precompiled (in assets.rb) by an old rule using a wildcard, which I missed, it's now working correctly.

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.

Override LESS variables

I have the following stack:
Symfony2
Twig with lessphp filter installed.
Twitter Boostrap
In base.css i have:
// base.less
#import '/path/to/bootstrap.less'
#linkColor: 13px;
Variable name is not important at all. It can be any other variable used in bootstrap. It just doesn't get overridden. But if i put the variable into separate .less file and import it in base.less everything works as expected:
// base.less
#import '/path/to/bootstrap.less'
#import '/path/to/variables.less'
and
// variables.less
#linkColor: 13px;
Why does this work and the other not? Looked up for the docs (less/lessphp) but couldn't find anything related to this. (or i didn't know where to look).
Can someone explain why is this happening?
It looks like it's a bug in the lessphp compiler. Take a look at the github issue. Your workaround, to put the variable declaration into another file and also import it works just fine. Thanks by the way ;)
This is happening because you override the variable after it's been used to define all the Bootstrap styles.
I solve this problem this way:
Create my own main.less that imports my own bootstrap.less.
My own bootstrap.less is just the Bootstrap's bootstrap.less file copied over to my own folder with import paths changed accordingly, but with one exception: it imports by own variables.less instead of the Bootstrap's one.
My own variables.less imports the Bootstrap's variables.less and then overrides the ones I need.

Resources