8000 SCSS @use vs CSS @layer Problems.... plz fixed.. this issues.. · Issue #3842 · sass/sass · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

SCSS @use vs CSS @layer Problems.... plz fixed.. this issues.. #3842

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account relat 8000 ed emails.

Already on GitHub? Sign in to your account

Open
rebehayan opened this issue Apr 19, 2024 · 11 comments · May be fixed by #3843
Open

SCSS @use vs CSS @layer Problems.... plz fixed.. this issues.. #3842

rebehayan opened this issue Apr 19, 2024 · 11 comments · May be fixed by #3843
Labels
enhancement New feature or request planned We would like to add this feature at some point

Comments

@rebehayan
Copy link

While using CSS's @layer in scss,
I found that it did not work in files that had to be compiled at the top level.

The contents of my compiled file are as follows.

//style.scss
@layer reset, components, utility;
@use 'components';
@use 'pages';

The problem in that code is
@use must be at the top of the code
This problem seems to have arisen because it is similar to the @layer concept in CSS.

Is there a way to fix this problem or can it be fixed in a future update?


I wrote this issue through a translator.
Some expressions may be strange.

@nex3 nex3 transferred this issue from sass/sass-site Apr 19, 2024
@nex3
Copy link
Contributor
nex3 commented Apr 19, 2024

We generally recommend wrapping partials in mixins, so that instead of having your @use rules emit styles as a side-effect you can choose exactly where and when they're emitted. For example:

@use 'components';
@use 'pages';

@layer reset, components, utility;

@include components.styles;
@include pages.styles;

That said, we should probably move the @layer rule to the top of the output stylesheet as we do for plain-CSS @import so that this pattern is possible without forcing users to use mixins.

@nex3 nex3 added enhancement New feature or request planned We would like to add this feature at some point labels Apr 19, 2024
nex3 added a commit that referenced this issue Apr 19, 2024
These rules are only allowed at the beginning of stylesheets. Allowing
them anywhere in Sass and moving them to the top of the output matches
the behavior of plain-CSS `@import` rules.

Closes #3842
@nex3
Copy link
Contributor
nex3 commented Apr 20, 2024

Looking into this deeper: a @layer statement is actually allowed anywhere in a stylesheet that the block form is, so while it's allowed to be interspersed with @imports it's not required to be. That changes the way we'd handle this situation.

Also, a better alternative for handling this might be to put your @layer rule into its own file, at which point you don't need to use mixins at all:

// _layers.scss
@layer reset, components, utility;
// styles.scss
@use 'layers';
@use 'components';
@use 'pages';

Or better yet, @use layers from the files that specifically refer to the layers in question, since it'll be guaranteed to be emitted before those files.

@nex3
Copy link
Contributor
nex3 commented Apr 22, 2024

So we've got an interesting design question here. Currently, the following Sass file:

@layer foo;
@import 'bar.css';

produces:

@import 'bar.css';
@layer foo;

This is a clear violation of CSS compatibility, since the input is valid CSS as-is and the output has different semantics. On the other hand:

a {b: c}
@layer foo;

produces the correct output, behavior that should be retained. That raises the question of how to handle a case like the following:

a {b: c}
@layer foo;
@import 'bar.css';

Should this @layer rule be moved to the top of the file like the @import? Or should it remain in place like the style rule? I can see arguments for both options. I think I lean towards the latter, though—I don't want to encourage users to write useless @import rules just to force a @layer to be hoisted.

@rebehayan
Copy link
Author
// _layers.scss
@layer reset, components, utility;
// styles.scss
@use 'layers';
@use 'components';
@use 'pages';

I used this method and solved it.
@import was not used because it is not recommended by SCSS.
Thank you for your comment.
Hope you have a happy day.

@nex3
Copy link
Contributor
nex3 commented Apr 25, 2024

Re-opening because we still need to fix the issues described in #3842 (comment)

@nex3 nex3 reopened this Apr 25, 2024
@Maximillion195
Copy link
Maximillion195 commented Oct 3, 2024

I'm also having the issue in #3842 (comment) i'm trying to import css from a ui library with the specified layer but I need to declare the layer order prior. When the css is generated, the layer order declaration is placed after the imports.

This

@layer defaults, uilib, components;
@import '~@ui/lib/Button/Button.css' layer(uilib);
@import '~@ui/lib/reset.css' layer(defaults);

Generates this

  !*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/@ui/lib/Button/Button.css' (layer uilib) ***!
[class^=button]{box-sizing:border-box}
  !*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/styles/global.scss ***!
@layer defaults, uilib, components;

I tried separating them out in files with @use imports but it doesn't make a difference.

@use 'layers';
@use 'frameworks';

@hammad-awan
Copy link
hammad-awan commented Nov 25, 2024

So we've got an interesting design question here. Currently, the following Sass file:

@layer foo;
@import 'bar.css';

produces:

@import 'bar.css';
@layer foo;

This is a clear violation of CSS compatibility, since the input is valid CSS as-is and the output has different semantics. On the other hand:

a {b: c}
@layer foo;

produces the correct output, behavior that should be retained. That raises the question of how to handle a case like the following:

a {b: c}
@layer foo;
@import 'bar.css';

Should this @layer rule be moved to the top of the file like the @import? Or should it remain in place like the style rule? I can see arguments for both options. I think I lean towards the latter, though—I don't want to encourage users to write useless @import rules just to force a @layer to be hoisted.

Hoisting through an @import does not work anyway.

I have moved my layers definition to a layers.scss and imported that as the first import at the top of my styles.scss file and it is still placed after all imports in that file. All @import statements are also hoisted above everything even a @forward which must appear first in a styles.scss file.

Isn't this a significant bug since it doesn't actually allow layering to work correctly?

@bbroekhuizen
Copy link

Experiencing the same issue. Tried the options which are mentioned here, but still can't get it to work. I want to do some future proofing so i don't have to rethink / refactor everything after 1 or 2 years when Dart Sass 3.0 is the new standard, so this is holding me back significantly.

@hammad-awan
Copy link
hammad-awan commented Nov 28, 2024

I have worked my way around this. I don't know if my situation is similar or applies to anyone else's but I am posting it so that others may possibly glean some benefit from it.

I had to use multiple third party libraries, one of which I had to forward into my sass entry point styles.scss according to its documentation, so I did the following.

I had a first-library-forward.scss which contained a @use "first-library-core" with (...) variable overrides statment and a @forward "first-library" statement after it. This was part of the procedure I followed as part of the first-library documentation.

@use "first-library-core" with (...);

@forward "first-library";

// additional styles...

Then I created a first-library-theme.scss in in order to wrap this third party library in a layer and placed my layer precedence at the top of the file like so:

@use sass:meta;

@layer second-library-layer, third-library-layer, first-library-layer;

@layer first-library-layer {
    meta.load-css("first-library-forward");
}

Then in my styles.scss I did the following:

@use sass:meta;

@forward "first-library-theme";

@layer second-library-layer {
    meta.load-css("...path to second-library");
};

@meta.load-css("...path to third-library"); // already wrapped in a layer

// ...additional styles

So, in short, I used sass:meta instead of import statements to bypass the hoisting. The layer precedence was the first statement in the generated css file styles.css due to the forward and all of the other styles were "imported" correctly in their wrapped or pre-existing layers in the order they appeared in styles.scss.

@almeister
Copy link
almeister commented Apr 14, 2025

Looking into this deeper: a @layer statement is actually allowed anywhere in a stylesheet that the block form is, so while it's allowed to be interspersed with @imports it's not required to be. That changes the way we'd handle this situation.

Also, a better alternative for handling this might be to put your @layer rule into its own file, at which point you don't need to use mixins at all:

// _layers.scss
@layer reset, components, utility;
// styles.scss
@use 'layers';
@use 'components';
@use 'pages';
Or better yet, @use layers from the files that specifically refer to the layers in question, since it'll be guaranteed to be emitted before those files.

I am using the layers in a file approach on a current project which works fine and I don’t think it should be forced by design if it can be avoided.

@almeister
Copy link
almeister commented Apr 14, 2025

So we've got an interesting design question here. Currently, the following Sass file:

@layer foo;
@import 'bar.css';
produces:

@import 'bar.css';
@layer foo;
This is a clear violation of CSS compatibility, since the input is valid CSS as-is and the output has different semantics. On the other hand:

a {b: c}
@layer foo;
produces the correct output, behavior that should be retained. That raises the question of how to handle a case like the following:

a {b: c}
@layer foo;
@import 'bar.css';
Should this @layer rule be moved to the top of the file like the @import? Or should it remain in place like the style rule? I can see arguments for both options. I think I lean towards the latter, though—I don't want to encourage users to write useless @import rules just to force a @layer to be hoisted.

I’m also suffering the “can’t @use or @forward scss modules inside a css @layer” problem. So I’m mostly keen to resolve this 🤷‍♂️

Regarding hoisting of a @layer rule. Would this need to apply to @layer {…} enclosure rules too?

If it were for @layer order declarations only (eg: layer-1, layer-2;) then I would opt for hoisting it. Because I cannot imagine a case where hoisting the @layer order would break styling.

If it were for @layer {} enclosures (with nested styling), I would go for hoisting too. In theory, any @layer {} enclosure should result in correct styling, no matter where it’s moved to inside a file, no? Of course, preserving the order of multiple @layer {} enclosures would be necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request planned We would like to add this feature at some point
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
0