@charset "UTF-8";
That happens because something in Compass requires UTF-8, and Sass will generate that line if anything it is processing requires UTF-8. This is all fine...until you try to combine more than one of these standalone-css files with an asset packager such as Jammit.
Once Jammit combines all these CSS files, you end up with one CSS file that has multiple @charset directives in it, which according to the W3, is a no-no. Generating a CSS file with more than one @charset directive (and anywhere other than the very first line) is clearly against the W3's spec...but the only browser it seems to break is Safari.
But here's the thing: why do my CSS files need to have the @charset added by Sass when they don't actually get output with any non-ASCII characters?
In the end, my quick stop-gap solution was to remove them myself. I used to let Jammit do all the driving. During deployment it would force the regeneration of the CSS files and package them. Now I have to break out the Compass step and add my own sed command in order to remove all the @charset directives:
I think each one of these components has something to improve:
Safari:
If you don't support multiple @charset directives, I support you on that front. The spec says you're right. However...can't you just raise an error that says "ERROR: multiple @charset directives" or something? That would be much better than just randomly disabling half the CSS styles.
Sass:
Sass shouldn't add a @charset line if the generated CSS does not need it. If a mixin that uses UTF-8 is included but not used, and is not represented in the generated CSS, there is no need to add a @charset directive on its behalf.
Compass:
Compass is probably doing nothing wrong here. Though I do question why it needs to use UTF-8 characters. Maybe that's for a feature I haven't used yet.
Jammit:
In the end, I think Jammit is the real culprit here. It takes in N perfectly-valid CSS files and outputs one invalid CSS file. Jammit should remove duplicate @charset directives, and if they are conflicting, it should convert the charset of the conflicting stylesheet and into the charset being used by the output file.
4 comments:
The reason Sass adds the @charset directive here is that you're importing a Compass module that has non-ASCII characters. This module declares @charset UTF-8 at the top of the file, since that's necessary for the file being to be parsed.
Since Sass is a full CSS3 superset, it must preserve this @charset declaration, even if it detects that the output stylesheet has no non-ASCII characters. In general, if you aren't using the module with the @charset declaration, you shouldn't import it and you should never see the @charset. However, if you @import "compass", that will transitively import all modules, landing you with the @charset even if you aren't using that module.
Incidentally, Compass uses a non-ASCII character in its font-face mixin.
Thanks for that explanation, Nathan. The point about being a superset of CSS3 makes sense. I may take a look and see if I really need the font-face mixin. Good tip. (Thanks for chatting some of this out on IRC with me today too!)
UPDATE: I've filed an issue ticket with jammit for this: https://github.com/documentcloud/jammit/issues#issue/120
I may take a stab at forking the project and contributing a patch there...
Thank you so much for your post. This post really help me a lot and I have learnt some new things from your blog.
Post a Comment