What's the difference between only #use and #use as * SCSS rules? - sass

What's the difference?
#use 'scss/my'
and
#use 'scss/my' as *
I think it's same, isn't no use namespace, right?
but is it difference?

The Choosing a Namespace doc explains clearly.
By default, a module’s namespace is just the last component of its URL without a file extension. However, sometimes you might want to choose a different namespace—you might want to use a shorter name for a module you refer to a lot, or you might be loading multiple modules with the same filename. You can do this by writing #use "<url>" as <namespace>.
You can even load a module without a namespace by writing #use "<url>" as *. We recommend you only do this for stylesheets written by you, though; otherwise, they may introduce new members that cause name conflicts!
The point of the namespace is

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

Overriding a large number of !default values with the #use rule in Sass/Scss

I've got an SCSS module with a whole lot of overridable !default variables, and I'm trying to make use of it in a project using the new #use rule instead of the to-be-deprecated #import. Overriding a large number of variables used to be pretty straightforward. As long as I imported my variables before importing the module they would take precedence over the !default values.
Now, if I try to #use the module in the global namespace like so:
$h1-font-size: 40px;
#use 'my-module' as *;
I get an error - SassError: This module and the new module both define a variable named "$h1-font-size".
Apparently the proper way to do this is to use the with keyword like so
#use 'my-module' with (
$h1-font-size: 40px
);
But now my $h1-font-size variable isn't available to other parts of my code. It's only scope is in overriding the value in the module. If I tried to assign it to something else, I'd get an Undefined variable error.
So that leaves me doing this
$h1-font-size: 40px;
#use 'my-module' with (
$h1-font-size: $h1-font-size
);
.foo {
font-size: $h1-font-size;
}
This is the exact effect I want - a variable that overrides my module and is still available for use elsewhere. However this syntax is cumbersome for passing a large number of overrides. If I want to pass say 30 overrides, I need 30 variable definitions and then 30 lines within the with block to explicitly pass in 30 values.
Update / Edit
The answer from #Miriam Suzanne below makes it apparent I have oversimplified my use case for the purpose of asking a question.
Our shop has a set of mixins and base styles we use on many projects and I have been attempting to turn them into a reusable module to reduce the copy/pasting. Something like Bootstrap, with a lot of overridable !default values. Very much a work in progress, but the module itself can be seen here: Derekstrap.
This module is being developed in tandem with the first project we're actually using this on. The !default values are all in the module, and I would like to override them in my project.
Right now I have code in my main.scss (the primary entry point for stylesheets) that looks like this.
$base-font-family: 'Raleway', Tacoma, sans-serif;
$base-line-height: 1.8;
#use '~#evanshunt/derekstrap/index' with (
$base-font-family: $base-font-family,
$base-line-height: $base-line-height
);
I like to structure my scss files pretty granularly so ideally those variables would actually live in another file, and also be available to other files in the project.
If I do something like the following, where both my variables file and the module have a $base-font-family variable defined, it compiles but by variables don't override the module.
#use 'variables' as *;
#use '~#evanshunt/derekstrap/index' as *;
I suspect at this point the answer is that I need to add #use and/or #forward statements to my variables file(s), but it's breaking my brain a bit to figure out if I'll be able to successfully override different parts of the module in different parts of my project code. The suggestion above of just one variables file is also a bit of a simplification. How important will the order of the #use statements in my main.scss become if I am modifying the same namespace across the files being #used?
I get the purpose of scoping and passing values explicitly but I'd love some sort of shorthand or trick to accomplish this without writing so much extra code. As mentioned in my Sass feature request ticket I was hoping for a simple shorthand for passing one context into another like:
#use 'variables' as variables;
#use 'module' with variables;
This doesn't seem possible and I'm wondering if I need to completely rethink the way I structure SCSS files to achieve what I want. What can I do here?
I'm not entirely clear what you mean when you say the variable "isn't available to other parts of my code". The entire purpose of #use is to make those variables available – but inside a namespace. So you can do:
#use 'module' with (
$h1-font-size: 40px
);
.foo {
font-size: module.$h1-font-size;
}
or remove the namespace using as *:
#use 'module' as * with (
$h1-font-size: 40px
);
.foo {
font-size: $h1-font-size;
}
or forward the module while also adding configuration, to use in other files:
#forward 'module' with (
$h1-font-size: 40px !default
);
or both at once:
#forward 'module' with (
$h1-font-size: 40px !default
);
#use 'module';
.foo {
font-size: module.$h1-font-size;
}
I think that likely covers all the potential use-cases you might have for defining the same variable again?
In response to updates on the question…
Using the module syntax means that there is no global scope across files. That means every individual file needs to explicitly #use any-and-all required modules for that file. That means:
You will need to #use '~#evanshunt/derekstrap/index' (or similar) at the top of every single file that should have access to Derekstrap mixins, variables, or functions
Since index files are imported automatically, and default namespaces are generated based on the path, I'd probably #use '~#evanshunt/derekstrap' instead…
Namespaces are always local to the importing file, so you can #use '~#evanshunt/derekstrap' in one place (creating a derekstrap namespace), and #use '~#evanshunt/derekstrap' as * in another (removing the namespace), and still #use '~#evanshunt/derekstrap' as derek in a third place.
The goal of !default "configurable" variables is that they can be pre-configured before any compilation. That has to happen "first time" a module is used. If you want to do that in a file all to itself, you can:
// _config.scss
#use '~#evanshunt/derekstrap' with (
$h1-font-size: 40px,
);
// main.scss
#use 'config'; // keep this path first...
#use 'anything-else';
// _anything-else.scss
#use '~#evanshunt/derekstrap';
// derekstrap.$h1-font-size will already be configured by config.scss
Those values can only be pre-configured once - meaning the compilation will start with the configuration value. But you can update those variables any time in any file:
// _anything-else.scss
#use '~#evanshunt/derekstrap';
derekstrap.$h1-font-size: 32px;
// The $h1-font-size now has a value of 32px
// for any file to uses derekstrap later in the compilation
On my site, I use a combination of both approaches - just inside my one color config file:
https://github.com/mirisuzanne/mia/blob/main/src/scss/config/_color.scss
I have the #use … with pattern for configuring cascading-color-systems, but I also use accoutrement tools without configuration, and then override tools.$colors.
You can get quite a bit more complex by adding in layers of forwarding, but this should get you started. Remember:
The variable $h1-font-size exists inside the '~#evanshunt/derekstrap' module.
That module can used multiple times, and given a different namespace each time. The module is always the same module, but namespaces are local.
Pre-compile "Configuration" can only happen the first time a module is used, but you can continue to override those variables at any time.
Much like before, there is only one Derekstrap $h1-font-size variable, and it takes on different values over the course of compilation. what's new with modules is only that you need to explicitly #use Derekstrap in every file that wants access to that variable.
I understand it can take some getting used to, but in the end I've found my code is much more organized. You might want to set up a test project and play around, until the mental model makes more sense.

What does it mean to "pollute the global namespace"?

In ruby, some gems choose to "pollute the global namespace".
What does this mean?
How can I see where it's happening?
Why would a gem need to do this?
When faced with two gems that are polluting the global namespace and conflicting, what tradeoffs am I making when I choose to "isolate" one?
For example:
I'm using two gems that are both polluting the global namespace: pry and gli so I'm not able to place my binding.prys where I want anymore.
One solution is to wrap the entire cli in a module:
module Wrapper
include GLI::App
extend self
program_desc "..."
...
exit run ARGV
end
Now I'm able to use my binding.prys wherever I want.
Why did this work?
What tradeoffs am I making when I choose to do "isolate gli"? Or is it "isolate the GLI::App module"?
Ruby has a singular root namespace shared by all code and any constants and globals you define there are universal through the whole application. This makes conflict inevitable if you're not careful about namespacing things.
The module construct is there as a namespace primitive, all constants will be local to that, all classes defined within it. You can also use a class as a namespace if you prefer, it's up to you.
Forcing the include of something into the root namespace is a big problem. That's usually only done in quick scripts that are fairly tiny and self-contained. That's a bad habit to get into when you're doing anything non-trivial as it mashes together all the constants and methods in those two contexts, potentially over-writing them.

What does an underscore at the start of an *.scss file name indicate?

I've had a look into CSS setups for a couple of projects that other people developed and I can understand most of what's going on.
The programmers have, however, created some files whose names start with the underscore (for example: _variables.scss). I have seen files named like this in both of the projects.
I can't figure out what this convention represents. Is there a special reason why the people are naming the files this way?
The only reason I can find to use underscore before the name of the partial is what's described in the Sass docs here:
The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file.
Any SASS files not beginning with an underscore will be rendered on their own, which will fail if they are using variables or mixins defined elsewhere.
In the end I have concluded that the underscore is just used to clarify that it is a partial file. We can also use a partial file without using an underscore as prefix.
Sometimes that naming convention is used for templates or template part files, you could find this being used in MVC frameworks.
In other places this might mean that this variable or file is private and can only be accessed by the server or the running program. It all depends on the language you're programming really, but this is simply a naming convention.
It's just a naming convention. When you want to define a name for an interface you define it with (_interface). This is just for compatibility issues, In some cases a program may include classes and interfaces And in order to distinguish between the two, you use _ for interfaces.
This is just one example as you can use it in the BLL layer when working with databases and so on.
It is an emphasis for other developer to notice the variables and objects.

Resources