csstools / postcss-normalize

Use the parts of normalize.css (or sanitize.css) you need from your browserslist
Creative Commons Zero v1.0 Universal
816 stars 40 forks source link

Update postcss-normalize to handle new `@use` sass syntax #47

Closed james-camilleri closed 3 weeks ago

james-camilleri commented 4 years ago

I'm in the process of writing some scss code and was delighted to find and use postcss-normalize, however it doesn't seem to handle sass's new @use module system. The issue comes about when trying to @import normalize before any other library:

@import 'sanitize';
@use 'some-other-library';

This results in the SASS compiler throwing an error:

SassError: @use rules must be written before any other rules.
    │
357 │ @use 'some-other-library';
    │ ^^^^^^^^^^^^^^^^^^^^^^^^^
    │

Changing the order of the @import statement will defeat the purpose of style reset/normalisation, and the plugin does not currently handle using the @use directive to include the normalize styles. A simple solution would just be to update the plugin regex to also handle the @use syntax.

Dan503 commented 4 years ago

The problem is in your Sass code, not postcss-normalize.

Sass is a CSS pre-processor.

PostCSS is a CSS post-processor.

In other words, by the time postcss-normalize is able to do anything, the Sass @use keyword has been compiled out already.

To fix your problem, use @use to import sanitize instead of @import.

@use 'sanitize.css/sanitize';
@use 'some-other-library';
james-camilleri commented 4 years ago

Would that not defeat the purpose of using post-css-normalize to only import subsections of normalize.css? Using @use 'sanitize.css/sanitize'; would import the entirety of the library and inject it into my final stylesheet, when the point of utilising post-css-normalize would be to selectively import subsections.

Dan503 commented 4 years ago

My understanding is that post-css-normalize works by removing the parts of sanitize.css/sanitize that aren't needed after it has already been fully imported into the css file.

Remember that post-css doesn't do anything until the sass has completely finished generated a full plain css file that PostCSS can then modify.

james-camilleri commented 4 years ago

I don't believe that's the case. The css seems to be imported through post-css, parsed via postcss-browser-comments: https://github.com/csstools/postcss-normalize/blob/fd294fd36463ed9dc378fd41bbf0b685d1d4f7fe/src/lib/postcssNormalize.js#L79 and then prepended to the final output here: https://github.com/csstools/postcss-normalize/blob/fd294fd36463ed9dc378fd41bbf0b685d1d4f7fe/src/lib/postcssNormalize.js#L90 I have currently worked around this by importing the whole file, but it's a pity to lose the functionality.

Dan503 commented 4 years ago

Ok right, I didn't fully understand how postcss-normalize works.

This isn't something that postcss-normalize will be able to fix because it is a difficulty with Sass which runs before PostCSS runs. I don't see Sass being eager to address this issue either because it is fundamental to how @use works.

The way I would work around the issue is to create a file that is just @import-sanatize and use @use on that.

// sanitize.scss
@import-sanatize
// main.scss
@use 'sanitize';
@use 'some-other-library';
Dan503 commented 4 years ago

... except it doesn't actually seem to work ☹ (See #46)

jonathantneal commented 4 years ago

Is the @import-normalize "opinionated.css" bug related to Sass?

Dan503 commented 4 years ago

No, it's just that sass needs to use the @import-normalize method of importing for it to not conflict with the native @import Sass functionality.

The @import-normalize method isn't working at all though as shown in #46

james-camilleri commented 4 years ago

To be honest I'm not sure if it would help either, sass seems to complain if any directive appears before the @use rule. The issue isn't with the @import, it's just that anything appearing before @use is now flagged as incorrect syntax.

romainmenke commented 3 weeks ago

Sorry, not going to resolve this issue.

This plugin itself introduces non-standard syntax. Making it compatible with sass which is also non-standard is taking things too far.

It would make more sense to have an extension on top of sass/scss with similar functionality as this plugin.