Font-Awesome icon indicating copy to clipboard operation
Font-Awesome copied to clipboard

fa-fw behavior is not the same when loading a page with Web Fonts versus SVG + JS

Open alexandrejobin opened this issue 2 years ago • 4 comments

Bug description

Hi everyone!

When using the SVG + JS version, there's always a delay between when the page is shown and when the icons are printed. This is normal. The problem that I have is that it also have a delay for the icons to take the width that they need with the "fa-fw" class compared to the Web Fonts. For exemple, here's the html code that I use:

<i class="fa-regular fa-user fa-fw"></i> User icon

Here's the result when using SVG + JS compared to Web Fonts:

Image 011

As you can see, when using the Web Fonts, the width is reserved because I'm using the "fa-fw" class. When the icon is printed, the space needed do not have to be adjusted. When using SVG + JS, "fa-fw" class do not apply a reserved width to the <i> tag. It only apply his style to the <svg> that is not yet printed so the user will see the flickering.

Is there a reason why the SVG + JS version do not have css that apply formatting to the <i> tag to prevent this kind of behavior? What seems to work good for me is to add "fa-regular" everywhere there's a "svg-inline--fa" class like so:

.svg-inline--fa,
.fa-regular,
.fa-solid {
  display: var(--fa-display, inline-block);
  height: 1em;
  overflow: visible;
  vertical-align: -.125em;
}
.svg-inline--fa.fa-2xs,
.fa-regular.fa-2xs,
.fa-solid.fa-2xs {
  vertical-align: 0.1em;
}
.svg-inline--fa.fa-xs,
.fa-regular.fa-xs,
.fa-solid.fa-xs {
  vertical-align: 0em;
}
.svg-inline--fa.fa-sm,
.fa-regular.fa-sm,
.fa-solid.fa-sm {
  vertical-align: -0.07143em;
}
.svg-inline--fa.fa-lg,
.fa-regular.fa-lg,
.fa-solid.fa-lg {
  vertical-align: -0.2em;
}
.svg-inline--fa.fa-xl,
.fa-regular.fa-xl,
.fa-solid.fa-xl {
  vertical-align: -0.25em;
}
.svg-inline--fa.fa-2xl,
.fa-regular.fa-2xl,
.fa-solid.fa-2xl {
  vertical-align: -0.3125em;
}
.svg-inline--fa.fa-pull-left,
.fa-regular.fa-pull-left,
.fa-solid.fa-pull-left {
  margin-right: var(--fa-pull-margin, 0.3em);
  width: auto;
}
.svg-inline--fa.fa-pull-right,
.fa-regular.fa-pull-right,
.fa-solid.fa-pull-right {
  margin-left: var(--fa-pull-margin, 0.3em);
  width: auto;
}
.svg-inline--fa.fa-li,
.fa-regular.fa-li,
.fa-solid.fa-li {
  width: var(--fa-li-width, 2em);
  top: 0.25em;
}
.svg-inline--fa.fa-fw,
.fa-regular.fa-fw,
.fa-solid.fa-fw {
    width: var(--fa-fw-width, 1.25em);
}

Reproducible test case

No response

Screenshots

No response

Font Awesome version

v6.1.2 and v5.x

Serving

Self-hosted

Implementation

CSS, SVG+JS

Browser and Operating System

All browsers

Web bug report checklist

  • [ ] I have included a test case because my odds go way up that the team can fix this when I do
  • [X] I have searched for existing issues and to the best of my knowledge this is not a duplicate

alexandrejobin avatar Aug 02 '22 19:08 alexandrejobin

Hi!

Thanks for being part of the Font Awesome Community.

I think this behavior should be expected when using the JS framework, out of the box, with async loading

However, it is possible to load the CSS on its own by disabling autoAddCss class and referencing it from a stylesheet tag

Ref: https://fontawesome.com/docs/apis/javascript/configuration#autoaddcss

@robmadole any thoughts?

tagliala avatar Aug 02 '22 20:08 tagliala

The problem will still occur if you disable autoAddCss et add the stylesheet manually in the header. It's because there's no styling on the <i> tag so the first thing the user see when the page print is the <i> and then the javascript code replace it with the <svg> tag. This will create a flicker to the user.

I've made a few demos to see the problem:

  • https://jsfiddle.net/6nb0qmpo/3/ On this one, I have deactivated the autoAddCss and autoReplaceSvg to simulate the flicker. Just press the "Add icons" button to apply the icons. You will get a flicker to show the icon but also a flicker when the icons will take his space in the page.

  • https://jsfiddle.net/ut6n018b/ On this one, I have removed the official stylesheet and replaced it with my version that I explained earlier. You will see that the space need for the icons when you use fa-fw class is already reserved so it's smoother for the user. The only flicker that you will see is the time it take to show the icon only.

  • https://jsfiddle.net/kn4oLhcq/ This one is the Web Fonts version. No flickering since that icons is applyed sooner.

alexandrejobin avatar Aug 03 '22 14:08 alexandrejobin

Thanks, I can see the issue now

The problem is that the base classes like fa-solid do not have their style, so display: var(--fa-display, inline-block); is not applied.

A workaround for fa-fw would be:

.fa-fw {
  display: var(--fa-display, inline-block);
}

Ref: https://jsfiddle.net/tagliala/2rankov6/

but the suggested solution requires that style to be applied to other classes (fa-light, fa-thin, fa-duotone)

@robmadole what do you think?

tagliala avatar Aug 04 '22 09:08 tagliala

Your workaround is only good for fa-fw class but you will still get the flickering effect on the other classes, for exemple, the fa-5x and all the others. My opinion would be that whenever you have the svg-inline--fa class, you should also have all the fa-light, fa-regular, fa-duatone, etc with it.

alexandrejobin avatar Aug 05 '22 02:08 alexandrejobin