elad2412 / the-new-css-reset

The New Simple and Lighter CSS Reset
https://elad2412.github.io/the-new-css-reset/
MIT License
2.25k stars 229 forks source link

@charset at-rule and bundlers/processors compatibility #71

Closed tommiv closed 1 year ago

tommiv commented 1 year ago

Hi, sorry if I miss something, but is there any particular reason to add an explicit @charset "utf-8"; here?https://github.com/elad2412/the-new-css-reset/commit/7f52a2b1a8299e9806668d082c810056069dd4e5. I'll try to explain what happens with my project because of this (please don't take it as offence because it's not implied).

Asking because: 1) it doesn't add any value nor solve any bugs unless the reset.css somehow intentionally served with a wrong charset header / tag attribute (see MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/@charset, the part before "Syntax", explaining how user-agent should decide which charset to use – it will eventually fall back to utf8 anyway) 2) even if it's served incorrectly, reset.css doesn't contain any non-ASCII symbol so it basically should look exactly the same in almost any encoding. 3) it might break backward compatibility with bundlers or pre/postprocessors


I'll stop on the 3rd reason for a moment. @charset rule MUST be the first piece of text in the entire file, regardless what's inside. Imagine some of this situations:

1) a bundler, let's say it's Webpack, packs some CSS files into one bundle. Yes, reset.css should be the first stylesheet in this file anyway, but there might be some situations when it's not. In this case the resulting file will be:

/* some defaults stylesheet goes first for whatever reason. Maybe it's some additional reset rules which are allowed to be overriden by reset.css or anything else */

@charset
/* reset.css contents goes here*/

In this case, the whole file is malformed and user-agent will probably reject it (I didn't check it but it looks so according to MDN)

2) [this is my case] a postprocessor, let's say it's postcss with a custom number of plugins, adds some @mixin rules into every file it encounters (it's like a banner-plugin for webpack). in this case the reset.css becomes

@mixin mymixin {
...
}

@charset
/* reset.css contents goes here*/

In this case, postcss just throws an error and compilation fails.

3) Of course there might be other use cases I'm not aware of


For now, I have the following solutions: 1) downgrade the-new-css-reset to v1.8.4. This is bad because I basically opt-out of any updates to the package 2) write a custom plugin to postcss which would remove the @charset manually. This is bad because I manually do something which is considered to be a hack 3) write a custom Webpack rule which treats reset.css differently than any other stylesheet in the project. Doable but looks like a hack too 4) remove the charset line with any other tool, like a pre-build step. This is bad for the same reason 5) use some community plugin which removes the charset instead of me. This is bad because there are two of such plugins, one of them is abandoned/archived and the other one is shipped as a part of a huge cssnano project

After an hour of fiddling with postcss documentation I have a working 2) solution, and it's awful:

const tempRemoveCharset = () => ({
  postcssPlugin: 'tempRemoveCharset',
  Once: (root) => {
    if (!root.source || !root.source.input || !root.source.input.file.includes('reset.css')) {
      return;
    }

    const charset = root.nodes.find((node) => node.type === 'atrule' && node.name === 'charset');
    if (charset) charset.remove();
  },
});
tempRemoveCharset.postcss = true;

So in the end I decided to just downgrade (the solution 1)

elad2412 commented 1 year ago

Thanks for the heads-up; this has been removed, even for the small risk of making issues.

See new version 1.9

oinochoe commented 1 year ago

@tommiv Hi~ tommiv,

The charset rule will be placed at the beginning of the document rather than the entire document. As mentioned in number 2, reset.css rarely contains an ASCII string like the following example.

[data-set="dragon"]::before
{
    content: ' ↗';
    display:block;
    width:10px;
}

I'm not sure about the backwards compatibility you mentioned in number 3.

As a result, I agree with the part that you think there will be no problem even if you remove it, so I think it will not matter if it is removed 🙏 .