Can SASS mixins and variables sit in different files? - sass

Hi I am trying to organise my sass files into separate chunks on a project using GULP. However when I import my mixins and variables in separate files:
File:variables.scss
//first import variables that might be used throughout all the other files
#import "common/_variables.scss";
File:mixins.scss
Mixins
#import "common/_mixins.scss";
Then try to access those mixins from other files for example
File:buttons.scss
#import "common/_buttons.scss";
I get the following errors when running gulp sass:
throw er; // Unhandled 'error' event
no mixin named 'foo'
or
undefined variable 'foo'
In spite of the mixins/variable being defined in the variable.scss and mixins.scss files. So gulp interrupts the task half way though and the stylesheet is not created.
Is there a rule in SASS that means the variables and mixins must all be imported in the same files using them? If this is the case, it is a problem as I have a lot of files I would like to keep separate and not have to keep importing both mixins and variables inside them.

The short answer is you dont have to import them into everyfile that might include them. However there does need to be a relationship somewhere, and how you do this depends on whether or not you are looking to build one single final CSS file - or a series of individual files.
If you want the former, you could consider having a master import file that does little more than import all the appropriate *.scss files, and have this be the main SASS file your gulp build script looks to compile.
You'll need to take care to import files in the correct order - so no importing a file that uses a mixin before the file that defines the mixin has been imported it's self.
So for example - personally I work with a main.scss file that is structured as
#import "common/_variables.scss";
#import "common/_mixins.scss";
// Now import the files that might use these vars/mixins
#import "common/_buttons.scss";
which is built via gulp to create css/main.css.
Should you want a series of CSS files - i.e. buttons.css, type.css, layout.css etc - then you would need to have the appropriate variables and mixin #import declarations in each file that calls them

I found the best solution for me with pre-concating SASS files with GULP.
Like in this example for STYLUS
gulp.src(config.projects.css.source)
.pipe(sourcemaps.init())
.pipe(mktimecss(__dirname+'/web'))
.pipe(concat('styles'))
.pipe(stylus({
'include css': true,
use: [nib()],
// compress: true,
linenos: false
}))
...... and so on .......

It is most definitely possible to have your mixins and variables in different files. In fact, I'd recommend any mixins/variables that you find yourself reusing, you should take a more global approach with them instead of importing them into individual files.
One of the best ways I've seen for organizing a directory of Sass files is called The 7-1 Pattern and makes the entire structure of styling so much easier to understand and build upon.
The most applicable piece of this organizational strategy to your question would be creating a main.scss file that imports every one of the files you plan on using. Make sure you're careful about the order that you import, though. You can't import a file that uses mixins or variables from a file imported after it.

Related

Sass 7-1 Pattern using #use and #forward

What's the correct way of setting up a Sass 7-1 Pattern using #use and #forward?
Example:
Sass 7-1 Pattern
Files:
./scss/abstracts/_variables.scss
$main-color: #222222;
./scss/abstracts/_index.scss
#forward './variables';
./scss/components/_card.scss
.card {
color: $main-color;
}
./scss/components/_index.scss
#forward './card';
./index.scss
#use './scss/abstracts/index' as *;
#use './scss/components/index' as *;
If #use and #forward were replaced by #import (which the docs say is deprecated) it would work but when using the new #use and #forward Syntax the card component which is imported after abstracts is not able to "see" the variables.
It works if abstracts/_index.scss is imported via #use into components/_card.scss.
If I were to use Sass 7-1 Pattern, is duplicating #use on multiple files across the 7 folders the correct approach? It seems like it kind of kills the need of a main Sass file importing all partials.
To whoever tries to enlighten me, I thank you in advance!
After consulting SASS #import documentation
Looks like it's being deprecated because it makes all imports global across the files from the point it's imported, making it easier to cause name-collision between multiple libraries.
You'll need to implement #use across your files but as said into #use
documentation about the main differences between #import and #use:
#use only makes variables, functions, and mixins available within the scope of the current file. It never adds them to the global scope. This makes it easy to figure out where each name your Sass file references comes from, and means you can use shorter names without any risk of collision.
And it's nice to keep in mind that:
#use only ever loads each file once. This ensures you don’t end up accidentally duplicating your dependencies’ CSS many times over.
So for your code to work just add to
#use "../abstracts/index" as *;
.card {
color:$main-color;
}

When importing a file with #use then: Error Undefined Mixin

I have a entry file:
#use '_mixins';
#use '_default';
Now when I use a mixin in default.scss it throws the error:
Dart Sass failed with this error: Error: Undefined mixin.
Since #use is encouraged I don't understand why this doesn't work. If I write #import like in the olden days it works well:
#import '_mixins';
#import '_default';
This way all is nice and dandy.
How do I have to use #use and still have everything available?
That may be because the use of the new rule #use has an high impact to the way you build your project structure. Using of #usechanges it dramatically:
With #import you add a file and the mixins/vars/modules are ready to use in every sass file you load later on.
With #use you have to load the special sass file you need (i.e. '_mixins') direct in the file where you want to use it direct ... not to the main file. (Yes: loading the mixins/functions/variables-files to EVERY single partial file where you want to use them is the NEW INTENDED way to write sass.
And one more point to your using of #use: If you load by #use 'mixins you have to call the mixin in your file in the separated namespace #include mixins.yourMixinYouCall. If you want to load the mixins without separated namespace you can do: #use 'mixins' as *.
This changing to seperate namespace has some advantages. But indeed that is a really big impact and a very hard discussed theme about the new way to build your sass files.
We had this this week and before posting that twice you may have a look to this posting:
The #use feature of Sass

Importing SASS variables with #use

I have been using LESS for years and am only just trying out SASS. I am having trouble with a very basic thing so I hope someone can help me out.
What I want to achieve is:
a file theme.scss (which is compiled into theme.css) contains separate components (for header, navigation, font etc.)
define variables for things like brand colours to be re-used in the components
I have got it to work with #import, but because that is (going to be) deprecated I want to use #use instead. According to https://sass-lang.com/documentation/at-rules/use that should be possible.
My file setup is like this:
|- style
|- _definitions.scss
|- theme.scss
|- components
|- component.scss
Then I have this in the files:
// theme.scss
#use 'definitions';
#use 'components/component.scss';
// _definitions.scss
$base-color: blue;
// components/component.scss
body {
background: $base-color;
}
But this doesn't work: my compiler (I'm using Prepros) just says it can't find the variable $base-color. :( Note: if I replace #use by #import it works just fine.
Help?
#import will never be depricated. Sass' devs are a sleepy bunch of ****. #use is only supported by Dart-Sass yet, I assume you are using Node-Sass, which most are. Therefor you need to use #import, which makes in most use cases no difference.
You can find the info right under the heading, its the first line, virtually everbody skips.

SASS partials: to be or not to be

Any soild reason I should prefer the sass partials over normal sass files (w/o leading underscore in the filename)?
I am not a full-time frontend developer and for now I use sass for simple organizing of my css - split styles into different files(modules/components), variables, functions, in-place calculations, mixins - I think that's all I do.
In general I create a single main sass files that combines all the files together like that:
// main.scss
#import 'vars'
#import 'funcs'
#import 'layout'
#import 'component/modal'
// etc.
And recently I noticed there is such thing as partials.
From the documentation I understand partials are independent files that are not exists on their own and are always a part of some other bigger modules.
By this logic it looks like vars.scss, funcs.scss are good candidates to be partials.
And what I can't understand is why _vars.scss is better than vars.scss.
The both variants will work well from the point of view of code splitting.
Possible reason is Compilation - the docs page says partials will not be compiled into separate css file. I can't agree that's a feature since it's fully under my control and depends only on how I configure the building tools I use. And anyway such sass internal things like variables/functions/mixins will never be translated directly to css - they only exist in the source code.
So I would like to understand maybe it's just a convention for visual separation internal files from others? You know there is a similar old practice of separation private/public members/variables in programming. Or maybe I just miss something?
Please advise what I can do with partials what I cannot do with normal files, are there any advantages of first ones?

Freemarker: difference between include and import?

I am trying to create two templates and use the variables of one .ftl (freemarker) file in another.
I don't really understand why I should use include vs import.
#include is very much like if you copy-paste the content of the included file into the place of the #include tag. #import also processes the target file, but doesn't output anything. Instead, it assigns the set of variables (the namespace) created by the imported template to the variables after the as keyword. As #macro-s and #function-s just create variables, #import is practical for pulling in a collection of utility macros and functions. Also note that #import-ing the same file for the second time does nothing (as the namespace is only populated once), while calling #include twice will process the target file twice.
As for JavaScript, FreeMarker runs on the server side, and the JavaScript runs in the browser. So the browser only ever sees the final output from FreeMarker.

Resources