FortAwesome / Font-Awesome

The iconic SVG, font, and CSS toolkit
https://fontawesome.com
Other
73.53k stars 12.2k forks source link

Strange/Weird characters on refresh (Self-hosted CSS compiled from SCSS) #17644

Open templeman15 opened 3 years ago

templeman15 commented 3 years ago

Describe the bug On random page loads or refreshing of page strange characters are displayed instead of the font awesome icons. Seems to very closely related to #15010 & #17611. However, it happens when using both fa classes and setting the content manually in css.

There is no trace of FA4 in the project.

To Reproduce

SCSS:

Screen Shot 2021-02-17 at 1 25 31 PM

Expected:

Screen Shot 2021-02-17 at 1 26 01 PM

Actual:

Screen Shot 2021-02-17 at 1 25 53 PM

Expected behavior Expected behavior is that the font awesome icons would display correctly.

Version and implementation Version: Font Awesome Pro 5.14.0 Browser and version: Google Chrome 88.0.4324.150 OS: Mac OS 10.15.7

Bug report checklist

tagliala commented 3 years ago

Hi!

Thanks for being part of the Font Awesome Community.

Are you using self-hosted icons?

templeman15 commented 3 years ago

Hi!

Thanks for being part of the Font Awesome Community.

Are you using self-hosted icons?

@tagliala yes we are! Thanks for the quick response :)

tagliala commented 3 years ago

Could you please try with the Pro CDN (not the kit, just the link to the plain css) and attempt to reproduce?

https://fontawesome.com/account/cdn

tagliala commented 3 years ago

Hi @templeman15

SCSS:

I just read and realised that it was a screenshot of the SCSS, and that doesn't help. Any chance to get a look at the CSS output served to the browser by your application?

According to the Sass library used by your application, you may have wrong CSS results:

image

templeman15 commented 3 years ago

Hello @tagliala!

Here is the output served from the app (this is when the page loads correctly):

Screen Shot 2021-02-18 at 1 49 52 PM

Here is the output css from the browser (this is when the strange character occurs):

Screen Shot 2021-02-18 at 2 02 43 PM
tagliala commented 3 years ago

Ok, thanks.

Please switch to a different Sass implementation, make sure that your CSS output contains properly encoded characters

Meanwhile, closing here

dkniffin commented 3 years ago

@tagliala I am also seeing this behavior intermittently.

Can you clarify: is there an issue using fontawesome with dart-sass?

dkniffin commented 3 years ago

After some more investigation, this might be due to us setting $fa-font-display: swap, as touched on in #14387

tagliala commented 3 years ago

Can you clarify: is there an issue using fontawesome with dart-sass?

Not with Font Awesome. There are some issues with escaping with some versions of Dart Sass, please take another look at https://github.com/FortAwesome/Font-Awesome/issues/17644#issuecomment-781647877

There is no Font Awesome involved in this simple snippet:

.search-icon {
    &::before {
        content: "\f002";
    }
}

If the content is compiled into content: "";, then you may experience issues and I advise to double check the output. It should look like this in the output CSS:

https://github.com/FortAwesome/Font-Awesome/blob/fcec2d1b01ff069ac10500ac42e4478d20d21f4c/css/fontawesome.css#L3396-L3397

After some more investigation, this might be due to us setting $fa-font-display: swap, as touched on in #14387

You should not use that value for Font Icons: GoogleChrome/lighthouse#10127

tagliala commented 3 years ago

Hi @dkniffin

I've investigated and

Can you clarify: is there an issue using fontawesome with dart-sass?

Yes, there might be, in the case that a Font Awesome SCSS compiled to CSS with Dart Sass or Ruby Sass is not correctly interpreted as UTF-8 by the browser.

Although this may be considered a browser issue, I think that we should do our best to prevent it and provide ASCII output.

This will be hopefully fixed (again) in FA v6. I'm going to reopen this issue for tracking purposes

Since this will be a breaking change in v5, so I don't know what the team will decide.

The workaround is to override all the $fa-var-* variables in _variables.scss and the fa-content mixin from _mixins.scss

Ref:

Reference fix:

/* _mixins.scss */
@function fa-content($fa-var){
  @return unquote("\"") + unquote(str-insert($fa-var, "\\", 1)) + unquote("\"");
}

/* _variables.scss */
$fa-var-500px: f26e;
tagliala commented 3 years ago

The breaking change happened between dart-sass 1.10.4 and 1.11.0, but I can't bisect to the specific change because I do not have a proper dart build system.

Ruby Sass 3.7.4 is also affected and the breaking change happened between 3.6.0 and 3.7.0

SassC 2.4.0 is not affected

I guess this is the change: https://github.com/sass/sass/blob/master/accepted/identifier-escapes.md

Ref: sass/dart-sass#427 sass/ruby-sass#90

tagliala commented 3 years ago

Solution

if you have PUA codes (e.g., content: "" instead of content: "\f26e") in the output CSS, check that:

  1. The served CSS file starts with @charset "UTF-8";; AND
  2. The HTML file referring the CSS has the <meta charset="utf-8"> meta tag

https://github.com/FortAwesome/Font-Awesome/issues/14660#issuecomment-790475966

⚠️ update

Unfortunately this is not enough. It may fix 99% of the cases, but not 100%

pydolan commented 3 years ago

FWIW, I still see the odd characters with FA ~5.14.0~ 5.15.3 (free) on a site with <meta charset="utf-8"> in the header. I haven't tried adding @charset to the CSS file, but that's on my TODO list. (I'm seeing it very intermittently on Chrome 90.x on Mac Big Sur)

With disclaimer about my limited browser internals knowledge, could it be a timing issue, where the font svg/wolff/ttf file isn't loading in time before the HTML renders the page?

tagliala commented 3 years ago

I don't know and I don't think so. <meta charset="utf-8"> should be the first tag in <head>

Will try to simulate this

Arecsu commented 3 years ago

I had this problem for so long and apparently I got rid of it by adding @charset "UTF-8"; at the beginning of my CSS file as suggested above. I already had <meta charset="utf-8"> in the html head, but seems like it wasn't enough.

Disclaimer: I don't use FontAwesome. I'm using the Inter font with their CSS import rules and CDN. I was searching about the issue and ended up here. Placed it right at the beginning of my CSS, just before the import font url.

Tested it plenty of times with different scenarios and I don't get the weird characters anymore. Everything works great.

tagliala commented 3 years ago

I had this problem for so long and apparently I got rid of it by adding @charset "UTF-8"; at the beginning of my CSS file as suggested above. I already had in the html head, but seems like it wasn't enough.

Thanks for this heads-up

mayankchd commented 2 years ago

We had this problem too, investigated a bit and then figured out that this problem started happening after we switched to dart-scss. Looks like dart-scss by default in prod mode removes the @chatset. This issue in sass-loader has a solution

tagliala commented 2 years ago

Unfortunately this did not meet the 6.x milestone because of backward compatibility.

This should only affect some users using both SCSS and dart-sass.

I suggest to double check that both HTML and CSS (HTML is not enough) files have the correct charset. Some build system like webpack may strip out the @charset from the compiled css. You may want to use another plugin to write it back in the file

danon commented 2 years ago

[...] This issue in sass-loader has a solution

More of an workaround, since it suggests disabling compression. Hardly a solution.

tagliala commented 2 years ago

This should have been fixed in dart-sass's 1.38.0 release

https://github.com/sass/dart-sass/releases/tag/1.38.0

sass/dart-sass#1430

dart-sass users, please give it a try

I'm personally not happy with the result, I would like to see this "fixed" in FA, so I'm leaving this open for the moment

danon commented 2 years ago

@tagliala We're using dart-sass version 1.49 and the bug still happens sometimes.

tagliala commented 2 years ago

@Danon could you please provide an excerpt from the output CSS file where icons are defined?

I'm interested in knowing if the output is using unicode characters ("") or their escaped form ("\f26e")

danon commented 2 years ago

@Danon could you please provide an excerpt from the output CSS file where icons are defined?

I'm interested in knowing if the output is using unicode characters ("") or their escaped form ("\f26e")

Can't since it happens randomly. About once a week for me.

tagliala commented 2 years ago

@Danon sorry, maybe I wasn't clear

I've asked an excerpt of the CSS file containing the rule of a Font Awesome icon taken from the website where you are experiencing the bug

In other words, the following code:

https://github.com/FortAwesome/Font-Awesome/blob/307f2c15e2d3bdf465b43df0d1486dcd249df2a1/css/fontawesome.css#L547-L548

but taken from your CSS

Rezyan commented 2 years ago

@tagliala I'm using Font Awesome with dart-sass to compile the SCSS files. And of course, I'm experiencing the same issue, randomly. For some reason, the issue happens more often when the web console is open or being opened.

Here is the code you asked @Danon for, but from my CSS output:

.fa-anchor::before {
    content: "";
}

Screenshot: bug

Hope this can help.

tagliala commented 2 years ago

Yes, thanks.

We are trying to sort this out without breaking backward compatibility but it is a little bit trickier

As per dart sass, I can see that this has been partially fixed in 1.38.0, please make sure that you are using >= 1.38.0

There is also a workaround, but we don't know yet if it will fix 100% of the cases and requires effort on developer side. If you want to test, I've provided a step-by-step guide here: https://github.com/FortAwesome/Font-Awesome/issues/18775#issuecomment-1073217558

Rezyan commented 2 years ago

We are trying to sort this out without breaking backward compatibility but it is a little bit trickier

There is also a workaround, but we don't know yet if it will fix 100% of the cases and requires effort on developer side. If you want to test, I've provided a step-by-step guide here: https://github.com/FortAwesome/Font-Awesome/issues/18775#issuecomment-1073217558

I'm not in a hurry, I'll wait for this issue to be fixed by Font Awesome. The issue happens quite rarely, and you just have to reload the web page again to temporarily fix it.

As per dart sass, I can see that this has been partially fixed in 1.38.0, please make sure that you are using >= 1.38.0

I'm using the 1.49.9 version of sass/dart-sass. So, I guess their partial fix doesn't really work for me!

{
    "devDependencies": {
        "sass": "^1.49.9"
    }
}
danon commented 2 years ago

I also have 1.49.0 and I'm experiencing the bug too.

@BrokenSourceCode Have you found a way to fix this bug on our end?

Rezyan commented 2 years ago

I also have 1.49.0 and I'm experiencing the bug too.

@BrokenSourceCode Have you found a way to fix this bug on our end?

Not really, but you can try to programmatically add the rule @charset "utf-8"; at the VERY TOP of your CSS output files (AFTER the processing of dart-sass). You may use something like gulp-header or webpack (with the BannerPlugin).

By the way, don't forget to put the HTML tag below inside the <head> tag:

<meta charset="UTF-8">
tagliala commented 2 years ago

Hi @BrokenSourceCode ,

as per my understanding, @charset "utf-8"; and <meta charset="UTF-8"> are not enough to fix 100% of the cases. Ref: #18775

@GameCharmer is testing a fix that we can implement without breaking backward compatibility (on expense of compile time and scss source size), so I would like to ask if there are any news (but I'm assuming no news is good news)

GameCharmer commented 2 years ago

@tagliala So far so good! We haven't received a single message about it from our users, and none of the development team has ran into it since implementing your fix. You definitely nailed it! :D

OwenPattison commented 2 years ago

@GameCharmer @tagliala This sounds great thanks for the continued effort.

Is there a timeline for this release?

robmadole commented 2 years ago

No ETA yet. @tagliala has done a lot of the ground work here but we'll need to make sure we've got this nailed down before we release it.

tagliala commented 2 years ago

we'll need to make sure we've got this nailed down before we release it.

Agree. An application I maintain suffers of the same issue, but I would definitely avoid such a change if it is not going to fix 100% of the cases.

More feedback would be welcome.

Here it is a guide on how to test the workaround manually:

I've tried to provide a step by step fix here: https://github.com/diowa/ruby3-rails6-bootstrap-heroku/pull/540

This is based on Font Awesome Free, so steps for Pro should be a little bit different

At the end of the procedure, double check that variables in the output css have the proper escaped entities:

  • .icon::before { content: "\f26e"; }
  • .icon::before { content: ""; }

NOTE: This change will make harder to update Font Awesome

Feel free to ask any question

nirt04 commented 2 years ago

Hey guys, we don't use font-awesome but we came across your issue while trying to solve this problem with our own library so how you realized sass is decoding the Unicodes in build time and causing broken content to the classes

we work around this by importing the CSS icons files directly to js and skipping the sass-loader.

before:

image

after:

image image
GameCharmer commented 1 year ago

@tagliala I updated from 6.0.0 to 6.2.0 with no luck using the previous fix. Swapping the function results in no icons at all (not even the broken squares), and updating the variables results in the F132 string being displayed as plain text. Any ideas? I'm still running the same SCSS compiler.

tagliala commented 1 year ago

I'm still running the same SCSS compiler.

which is scssphp?

Please let's continue on #18775 and please retry https://github.com/FortAwesome/Font-Awesome/issues/18775#issuecomment-1070853882

I need an updated version of https://github.com/FortAwesome/Font-Awesome/issues/18775#issuecomment-1070882454

GameCharmer commented 1 year ago

scssphp/scssphp v1.10.1

18775 is still locked for me.

with option false

@charset "UTF-8";
.icon::before {
  content: "";
}

with option true

.icon::before {
  content: "\f26e";
}

Update: Updated to v1.11.0, identical output as above

tagliala commented 1 year ago

@GameCharmer the output looks ok and I do not see any possible issue with that specific compiler

I cannot reproduce the issue, my previous use case works good with 6.2.0 and the output CSS is fine

Steps to manually fix are described in the ~comment~ individual commit messages. You should redo the work with 6.2.0 files, otherwise new icons will not be available

https://github.com/diowa/ruby3-rails6-bootstrap-heroku/pull/540

Screen

image

Output CSS (dart sass 1.55.0)

.fa-github:before {
  content: "\f09b";
}

As far as your output is like the one above, then the cause of this new issue may be different

For any other attempt on my side, I need a remotely reproducible test case, or a minimal docker container, since I do not have the libraries needed to work with scssphp

viniciusdeliz commented 1 year ago

I also have 1.49.0 and I'm experiencing the bug too.

@BrokenSourceCode Have you found a way to fix this bug on our end?

Any luck with the 1.54.0 update in sass? The change appears to be the same of the 1.39.0 that was supposed to fix this, but maybe it works this time? https://github.com/sass/dart-sass/blob/main/CHANGELOG.md#1540

tagliala commented 1 year ago

Any luck with the 1.54.0 update in sass?

There is a partial fix in 1.38.0, as per https://github.com/FortAwesome/Font-Awesome/issues/17644#issuecomment-1071144856

I can confirm that in 1.55.0 this issue has been partially fixed, in the meaning that codes in the private area are correctly escaped, letters and numbers aren't (would this be a problem? 🤷🏻‍♂️), and I can't see unescaped unicode characters in the output CSS, so the @charset rule is not being emitted

$ npx sass --version
1.55.0 compiled with dart2js 2.18.1
$ npx sass node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss

Partial output:

.fa-at::before {
  content: "\@";
}
/* ... */
.fa-0::before {
  content: "\30 ";
}
/* ... */
.fa-p::before {
  content: "P";
}
/* ... */
.fa-snowflake::before {
  content: "\f2dc";
}

Anyway, adding the @charset rule does not always work, in the meaning that sometimes you can still experience this issue (ref #18775), and, in addition to that, some upstream minifiers on top of Sass may decide to strip the rule out (webpack-based bundlers may do that), so probably a fix on Font Awesome is still needed for this issue

Rezyan commented 1 year ago

I also have 1.49.0 and I'm experiencing the bug too. @BrokenSourceCode Have you found a way to fix this bug on our end?

Any luck with the 1.54.0 update in sass? The change appears to be the same of the 1.39.0 that was supposed to fix this, but maybe it works this time? https://github.com/sass/dart-sass/blob/main/CHANGELOG.md#1540

@viniciusdeliz I updated sass to version 1.54.0 on July 30th (currently my version is 1.55.0), and since then I've already encountered the weird characters on refresh, several times, randomly. So, on my side, the issue is still not fixed, but it seems that the problem occurs less often than before (maybe it's just an impression).

Anyway, adding the @charset rule does not always work, in the meaning that sometimes you can still experience this issue (ref #18775), and, in addition to that, some upstream minifiers on top of Sass may decide to strip the rule out (webpack-based bundlers may do that), so probably a fix on Font Awesome is still needed for this issue

@tagliala I agree with you: a Font Awesome's fix is still needed for this issue. 👍

domenkozar commented 1 year ago

I've hit this one using parcel: https://github.com/parcel-bundler/parcel/issues/8713

domenkozar commented 1 year ago

I noticed that the css file doesn't get interpreted as css, so I investigated deeper into it. Opening up the debugger tools reproduced it consistently, so that was the first clue.

I had a theory that content-type: text/css; charset=utf-8 should be set as the header, which wasn't the case when I was serving files from nginx.

Following nginx.conf in the http section helped:

            source_charset utf-8;
            charset utf-8;
            charset_types text/html text/xml text/css text/plain text/vnd.wap.wml application/javascript application/rss+xml;

Now https://cachix.org will finally not get garbled fonts :rocket:

florent-cdl commented 1 year ago

Found that post that was exactly my problem : encoding mixin error with libsass https://github.com/sass/libsass-net/issues/24 The workaround work great @mixin pseudoFontIcon($content) { content: #{"\""+$content+"\""}; } a:before { @include pseudoFontIcon(\e003); // without single/double quotes here }

magynhard commented 1 year ago

For others, facing the same issue:

The problem with displaying the icons incorrectly when contained in unicode characters is Chrome related and happens only in Chrome and other Chromium based browsers (e.g. Edge or Vivaldi). I could not reproduce it on Firefox or Safari.

It is not related to FontAwesome, it is related to all Iconfonts using unicode. (Im my case my own font)

It can even be reproduced regularly the following way:

It works only once, if you want to repeat, you need to close the developer tools, reload the page, then reopen the developer tools again and reload again.

It seems, that chrome does not check or detect the format of the CSS correctly when the page is reloaded with developer tools open at the first time.

For me, the best solution was - as mentioned by others before - to add

@charset "UTF-8";

at the beginning(!) of the .css file to workaround the Chromium engine bug.

tagliala commented 1 year ago

Just to mention (again) that adding @charset "UTF-8"; will not fix 100% of the cases

I suggest to consider also changing response header via nginx or whatever proxy server: https://github.com/FortAwesome/Font-Awesome/issues/17644#issuecomment-1362785107

magynhard commented 1 year ago

If using escaped utf8 characters beginning with \f adding the charset to the css header seems to work always, but maybe not when having the real utf8 characters inside the css. I think changing the web server header to fix this is no good solution. In my opinion you should convert to escaped characters and add the charset. Especially, when the developer has no option or no easy way to configure the webserver. So you are independent of whatever webserver is used and have the control in your web project instead on the webserver layer.

tagliala commented 1 year ago

In my opinion you should convert to escaped characters and add the charset

I'm 100% for this solution, and I think that FA should output escaped chars, but unfortunately it's a breaking change :(

Upgrading to dart sass > 1.55 should also help (or maybe even fix)

nsunga commented 1 year ago

Solution

if you have PUA codes (e.g., content: "" instead of content: "\f26e") in the output CSS, check that:

  1. The served CSS file starts with @charset "UTF-8";; AND
  2. The HTML file referring the CSS has the <meta charset="utf-8"> meta tag

#14660 (comment)

⚠️ update

Unfortunately this is not enough. It may fix 99% of the cases, but not 100%

hello @tagliala !

so sorry to bring up such an old comment

I did read the update, but with this "fix" does that mean the minified code results in the unicode string (ie. "\f26e")?

at the moment, the minified css I have are all PUA (Private Use Area) codes even with the "fix"