css-loader: @import invalidates @charset declaration

  • Operating System: Windows 10
  • Node Version: v14.14.0
  • NPM Version: 6.14.8
  • webpack Version: 5.1.3
  • css-loader Version: 5.0.0

Expected Behavior

The @charset declaration at the top of the generated CSS file.

Actual Behavior

The @charset declaration is below the imported CSS. To determine fallback encoding the @charset declaration must be at the start of the file (https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding).

The sass-loader automatically prepends @charset "UTF-8" (or BOM if in compressed mode). This information seems to be lost after sending the CSS string through the css-loader.

Code

Expected CSS:

@charset "utf-8";

p {
    color: red;
    font-size: 72px;
}

.greet::before {
    color: blue;
    content: 'Привет, ';
}

Actual CSS:

p {
    color: red;
    font-size: 72px;
}
@charset "utf-8";

.greet::before {
    color: blue;
    content: 'Привет, ';
}

How Do We Reproduce?

https://github.com/intemarkus/css-loader-charset-error

npm install npm run build Open dist/index.html in browser with file://…/css-loader-charset-error/dist/index.html

In some browsers (Chrome, IE, Edge) the CSS content isn’t read as UTF-8.

The CSS file is generated with the MiniCssExtractPlugin, but the direct result of the css-loader is printed in the console window.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 5
  • Comments: 19 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Without webpack you will faced with the same issue, no problems on webpack side, modify src/index.html

<!DOCTYPE html>
<html>
    <head>
        <title>css-loader @charset error</title>
        <script defer src="./index.js"></script>
        <link href="./style-css-loader-only.css" rel="stylesheet">
    </head>
    <body>
        <p class="greet">Markus</p>
    </body>
</html>

How to fix? Just add <meta charset="UTF-8">, i.e.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>css-loader @charset error</title>
        <script defer src="./index.js"></script>
        <link href="./style-css-loader-only.css" rel="stylesheet">
    </head>
    <body>
        <p class="greet">Markus</p>
    </body>
</html>

Exactly, sometimes I do not have the ability to control the HTML or headers, and I must rely on this feature of CSS which is currently not usable.

Right now this plugin is resulting in CSS which is technically broken – the charset tag cannot be placed in the middle of a file. Browsers are forgiving about this, but they will not parse the charset tag. Changing the HTML may be a solution for some people, but it does not fix the fact that the charset tag is in the middle of the file which is the primary problem here.

Yes! If you control the HTML you can set charset to UTF-8. If you control the server you can set the charset in the Content-Type HTTP header.

However, I ran into this issue when I tried to open a print popup in Safari. I had no control over the server, so I couldn’t set any HTTP headers. On top of that, the <meta> tag seems to be ignored by Safari when the document is opened with window.open(). The encoding of the document is then determined by the Safari setting “Default encoding” which defaults to “Western (ISO Latin 1)”.

I added the print popup to my repository. The CSS is served with an empty Content-Type header and the document that is opened in a new window contains <meta charset="UTF-8" />.

The problem is that in some (rare) cases I need to be able to specify the charset of the file in the CSS.

It would be nice to have this fixed. Relying on returning the correct http headers is painful when hosting a static app.