Re-exporting scss functions or mixins - sass

I have the following 3 scss files:
// component.scss
#use 'componentFunctions' as componentFunctions;
/** Adding a default color theme to the component **/
#include componentFunctions.addColorTheme(...);
// componentFunctions.scss
#mixin addColorTheme($param) {
... mixin that creates a color theme for the component
}
// main.scss
#use 'component' as componentName;
/** I would also like to use the createColorTheme mixin in this file, to add a new color theme for this component, in case this module is loaded, how can I achieve this? **/
What I am trying to achieve, is to access the function defined in componentFunction.scss, in the main.scss file. The only way I've managed to do this, is to manually redefine the function in the component.scss file, but surely there has to be a better way around for this.
Strangely, if I am not re-namespacing my imports, everything works automatically. There is a possibility that I misunderstood how the #use functionality works in SCSS, could someone elaborate on how could I achieve the desired effect?

According to Sass docs:
Any styles loaded this way will be included exactly once in the compiled CSS output, no matter how many times those styles are loaded.
So you can use #use again in your main.scss file as the code below:
#use 'component' as componentName;
#use 'componentFunctions' as componentFunctions;
$newVar: componentFunctions.myFunction();
In that way you don't need to redefine the function in the component.scss.

Related

How to access variables imported with #use method in sibling imports

This is my main.scss file.
// Main
// Variables (variables.scss)
#use "../../../style/variables" as *;
// Custom Normalize (normalize.scss)
#use "../../../style/normalize";
// Site header (header.scss)
#use "sections/header";
Variables defined in variables.scss are not accessible in normalize.scss & header.scss. Is there a way to use them inside those files without separate #use 'variables' statement?
Or would you just use separate #use method for each file? I am a newbie, so I don't know what's better.
You have two options.
1. #import
If you use #import except #use for imports, then you can access variables defined in variables.scss inside the normalize.scss & header.scss.
But it has a disadvantage. It is difficult to trace where your variables and mixins are coming from because #import enables an endless chain of imported files. It also allows for overlap and makes it difficult to trace back why your perfect css breaks. This is a problem especially with complex file structures and projects with multiple contributors and global libraries, which is why #import is no longer recommended by Sass.
2. #use
It also works like #import to break our stylesheet into smaller sections and load them inside other stylesheets. The key difference is how you access the original files' members. To do this you will need to refer to the namespace of the original file.
Here's an example of simple SCSS partials.
_variables.scss
$primary_color: #000;
_header.scss
#use 'variables';
.header {
color: variables.$primary_color
}
If you need more info read this article - https://www.liquidlight.co.uk/blog/use-and-import-rules-in-scss/
Let me know if you need further support.

How can I provide configuration variables to a Sass/SCSS file before including it?

I'm migrating a Stylus library to SCSS since Angular 12 has deprecated Stylus and I'm in that impacted 0.3%. I've run into something we were doing that I'm not sure how to convert to SCSS—maybe it's impossible.
Let me lay this out simply: I work on several projects that all use loads of the same styles, so we put those styles together into one style sheet in its own NPM package. We can then just grab #import '#company/design/styles'; and suddenly we've got all of our regular styles and variables and mixins available in the project, or we can import #import '#company/package/styles/common'; for just the variables and mixins.
The thing is, our projects might need to configure the library before we import it. Suppose the library contains this bit:
// #company/package/styles/_forms.scss
input:invalid {
background: url('/assets/input-error.svg') no-repeat center right;
}
Not every project will have /assets/input-error.svg at that exact location. Maybe one of my projects has to use /subfolder/static/input-error.svg.
I could include this then overwrite input:invalid { background-image: url(...) } to supply it with the correct location, but there may be many references to this particular file and many other assets on top of that to correct. So we instead, in our Stylus library, we introduced an $asset-input-error variable that points to /assets/input-error.svg by default and did something like this:
// #company/package/styles/_forms.scss
input:invalid {
background: url($asset-input-error) no-repeat center right;
}
// the local project
$asset-input-error: '/subfolder/static/input-error.svg';
#import '#company/package/styles';
The above is heavily simplified and isn't actually legitimate SCSS, but I hope it conveys what we're trying to do: we want to set up what are effectively environment variables in our SCSS, include the common style sheet, and have it use those variables.
The thing is, I'm not sure what the legitimate or idiomatic approach is to do this in SCSS. Unlike Stylus, which has a global scope for its variables, SCSS would have me #use '../config'; and reference config.$asset-input-error, and from outside the library there's no way I see to change the configuration to point that asset to a different location. I'm sure SCSS has a way for me to do this, but I'm not sure what it is. Do I convert the entire library into a giant mixin to which I pass optional configuration? Do I do something with global variables? Something else?
How can I provide variables to my SCSS style sheet to configure it as part of including it in a project?
Ultimately the end goal here is just to be able to say to the library things like: “the assets to reference are here” (very important) or “the error color is this in this particuilar project” (less important).
Using #import
You can use global variables declared before the #import as you stated.
SCSS Documentation for this method
#company/package/styles/_forms.scss
$asset-input-error: '/subfolder/static/input-error.svg' !default;
input:invalid {
background: url($asset-input-error) no-repeat center right;
}
#company/package/styles/styles.scss
#import 'forms';
local.scss
$asset-input-error: '/different/path/input-error.svg';
#import '#company/package/styles';
CodeSandbox Demo
Using #use [...] with
You can also hop aboard the #use train if you prefer to future-proof your library.
SCSS Documentation for this method
SCSS Documentation for using mixins
SCSS Documentation for configuring forwards
#company/package/styles/_forms.scss
$asset-input-error: '/subfolder/static/input-error.svg' !default;
input:invalid {
background: url($asset-input-error) no-repeat center right;
}
#company/package/styles/styles.scss
#forward 'forms';
local.scss
#use 'styles' with (
$asset-input-error: '/different/path/input-error.svg'
);
Sadly CodeSandbox and StackBlitz don't support dart-sass, so I don't have a live demo for this but I tested it on the latest version of sass from npm.

Overriding an scss variable by referencing other variable

Technically this isn't a boostrap thing, it's a scss thing, but Bootstrap is the context of which I am having issues. I am changing the default value of some values in bootstrap. One particular variable, I want to reference another bootstrap variable.
So I have my own file:
#import "_variable.overrides.scss";
#import "bootstrap.scss";
my _variable.overrides.scss looks like this:
$secondary: lighten($primary, 10%);
I can't do that because $primary is undefined since I am importing my overrides scss first. If I import boostrap.scss first, it doesn't override, because overrides have to come before the default variable definition.
Is there any way to override one variable by referencing another variable?
Basically, this has been answered before here and here. You need to first #import any variables you want to reference in your custom SCSS..
Since $primary lives in _variables.scss, you need to #import _variables.scss and _functions.scss (since this is ref'd by _variables.scss):
#import "bootstrap/functions";
#import "bootstrap/variables";
Then, as explained in the docs, your custom vars will override Bootstrap's because all the Bootstrap variables use the !default flag, which means they won't take precedence over your custom vars which are imported before Bootstrap. So the entire SCSS would look like (you may need to edit the paths):
#import "bootstrap/functions";
#import "bootstrap/variables";
#import "_variable.overrides.scss";
#import "bootstrap.scss";

Create selectors with no declaration

I am planning to use SASS by creating [_partial] and use [#import].
Question: How can I create selectors with no declaration?.
I will of course populate the selectors with declaration,
but that input comes from the other [_partials]. Have I understood correctly that SASS will delete a selector that has no declaration? Is there any workaround?
My partials structure looks as below.
#import '_1-partial_variables.sass'
#import '_2-partial_divs_only.sass'
#import '_3-partial_wrapper.sass'
#import '_4-partial_divs_layout.sass'
What I have tried so far:
In [_2-partial_divs_only.sass] I have tried:
.div-1
(the build executes without errors, but the div itself is not created).
.div-1 {};
(the build script says, "Error: Expected newline".
What about same scenarios using SCSS as source file?
The results are exactly same, a selector with blank declaration, is not created.
My build-line is:
sass --no-source-map main.sass main.css
Seems this works in order for the SASS compiler to create the selector [.div-1]:
.div-1
/*! keep */
This works also:
.div-1
/**/
As the source is a SASS file, I do not add [{}] nor [;].
Those characters are being created automatically when building from SASS to CSS.

Share SASS variables between files, without importing or referencing variables file?

Is it possible to share variables between files, without importing my variables file in every file? Here's an example:
Variables.scss
$primary: #0000FF;
HelpPage.scss
#help-page-container {
background: $primary;
}
Core.scss
#import "Variables.scss";
#import "HelpPage.scss";
Core.scss is the only file that gets compiled. All my single-page files, common CSS classes, and Variables.scss is included in this file.
If I want to use $primary inside my HelpPage.scss file, I would need to either do:
#import "Variables.scss";
or
/// <reference path="Variables.scss" />
Either one works. However, if I have 20 pages, I would need to import/reference the variables file at the top of each and every one of them, just to make Visual Studio happy and not throw a
Undeclared variable
error at me.
Have you read this?
http://thesassway.com/beginner/how-to-structure-a-sass-project
Essentially you would import _variables.scss and _help-page.scss into core.scss
This way helppage partial has access to all variables.

Resources