React-fontawesome: NextJS huge icon flash on initial page load

Created on 27 Apr 2019  ยท  25Comments  ยท  Source: FortAwesome/react-fontawesome

For posterity, this kills the unwanted flash of huge icon in NextJS:

// _app.js
import React from 'react'
import App, { Container } from 'next/app'

import { config } from '@fortawesome/fontawesome-svg-core' // ๐Ÿ‘ˆ
import '@fortawesome/fontawesome-svg-core/styles.css' // ๐Ÿ‘ˆ
config.autoAddCss = false // ๐Ÿ‘ˆ

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' // ๐Ÿ‘ˆ
import { faBook } from '@fortawesome/pro-solid-svg-icons' // ๐Ÿ‘ˆ

// Generic NextJS _app.js from https://github.com/zeit/next.js/#custom-app
class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return { pageProps }
  }

  render() {
    const { Component, pageProps } = this.props

    return (
      <Container>
        <FontAwesomeIcon icon={faBook} /> /* ๐Ÿ‘ˆ */
        <Component {...pageProps} />
      </Container>
    )
  }
}

export default MyApp

Most helpful comment

Like @ryandrew14 I found an workaround until they don't resolve this issue.

<FontAwesomeIcon icon="user" width="16" />

I'm using the width property to set icons default size, so, when the CSS (SCSS in this case) completly loads they change to the size the icon really is. No, this don't stop the icon to "blink" sizes, but small (or simply the body default font-size) is better than the bigger ones.

And, when they resolve this (or someone found a better solution) I'll simply use an Regex match replacer in VS Code to remove this workaround. Ugly, but, sometimes...

All 25 comments

Feel free to close after reviewing to make sure I'm not teaching people wrong.

(I know library.add() is probably more performant but it's really annoying to use so... I don't.)

I saw this problem with Gatsby as well. The workaround I found was just to use CSS to size the icon with em at the same value I was sizing the icon with (3x == 3em). This strikes me as something that shouldn't need any sort of workaround, though, so a fix for this would probably be optimal.

Like @ryandrew14 I found an workaround until they don't resolve this issue.

<FontAwesomeIcon icon="user" width="16" />

I'm using the width property to set icons default size, so, when the CSS (SCSS in this case) completly loads they change to the size the icon really is. No, this don't stop the icon to "blink" sizes, but small (or simply the body default font-size) is better than the bigger ones.

And, when they resolve this (or someone found a better solution) I'll simply use an Regex match replacer in VS Code to remove this workaround. Ugly, but, sometimes...

I wonder if width="0" would be better? Basically just make it invisible until it renders the CSS for it.

@corysimmons Yep, in some cases only. I've chosen "16" cause is my default body font size. So, if I considerated there most of the icons will be rendered in with this size, the "blink" effect will be lesser. With width="0" it's guaranteed that the "blink" effect will occur in every icon render.

So, at the end of the day, this workaround work with what match better for you, "blink" effect in all icon render to be consistent, or, the effect in a "few" to try hide.

Cool.

Closing as I think these are enough suggestions for the would-be Google searching dev.

@corysimmons I'm a little late to this party but your recommendations are correct. That's how we suggest this be solved.

I'm going to update the documentation to reflect this.

@robmadole @corysimmons May I suggest you make width/height a default property of say 20x20 or some other small, arbitrary number? If you read through https://www.sarasoueidan.com/blog/svg-style-inheritance-and-fousvg/ you'll find that CSS and other properties have higher priority than the width/height element attributes, so it would be backwards compatible.

And, if you recommend people to set width="0" then you should do it yourself, to have a library with the element of least surprise.

Furthermore, width is not a property in your typescript declarations for this component:

image

My 2 cents. I hope you agree.

The way I overcame the TS issue (until it is resolved in the library) is:

Add this to a global declarations:

import { Props } from '@fortawesome/react-fontawesome'

declare module '@fortawesome/react-fontawesome' {
    export function FontAwesomeIcon(props: Props & { width: number }): JSX.Element {}
}

@haf tbh I just stopped using FontAwesome. I was only using a handful of icons and the entire setup (combined with their new subscription business model) just isn't worth the hassle.

(sorry misclicked to reopen/close)

With Gatsby, I fixed this issue with:

import '@fortawesome/fontawesome-svg-core/styles.css';

We have a PR up that addresses the way you can use react-fontawesome with Next.js

https://github.com/FortAwesome/react-fontawesome/pull/300

Back with Next 5 I just did <script src="https://storage.googleapis.com/studylink/libs/fontawesome-pro-5.3.1-web/js/all.min.js" />, still works with Next 9. But I use my own CDN.

I don't remember having huge icons, but now that I'm setting it up again I'm encountering the same problem... Gonna force width/height as well I guess... A proper solution would be great.

@robmadole That doesn't seem to solve this issue?

@haf the issue with the large icons?

It does fix the issue with large icons, the tutorial in https://github.com/FortAwesome/react-fontawesome/pull/300

But I haven't read it before posting my last comment. Everything is fine now :)

No, the tutorial doesn't mention witdth=0 and it doesn't add the width attribute to the typescript bindings either, see https://github.com/FortAwesome/react-fontawesome/issues/234#issuecomment-493606728 โ€” adding the css style sheet sometimes help, but only if it's added and made to be requested at the very start, and not modularly later during the app life-cycle. But nextjs and the like chunk these things arbitrarily without user interaction, so just stating to "add it" is no the solution.

Using width=0 is too aggressive. Let's fix the underlying issue where the CSS is not loaded before the icon is rendered and begins to paint.

@haf can you provide a reproducible example where the approach from #300 doesn't work? Even with chunking this should add the CSS to the DOM before the icon. I can't imagine how this would fail.

It only happens after the compilation unit is large enough as far as I understand. Which makes it hard to repro. I can repro it with my site and then give you a link and the code I use for this?

@haf yes that would be fantastic.

Note:

I use SVG icons (not react/vue/etc)

I fixed this by adding this snippet to my <head>:

<link href="https://use.fontawesome.com/releases/v5.12.1/css/svg-with-js.css" rel="stylesheet"></link>

Source: https://fontawesome.com/how-to-use/on-the-web/other-topics/server-side-rendering

With Gatsby, I fixed this issue with:

import '@fortawesome/fontawesome-svg-core/styles.css';

This also works in Next.js in April 2021 ! โ™ฅ๏ธ

i know this is closed , but i found another working solution in case anyone wonders.

class Test extends React.Component {
    constructor(props) {
        super(props);
        this.state = ({
            ready: false,
        })
    }

    componentDidMount() {
        this.setState({ ready: true });
    }

    render() {
        return (
            <div>
                {this.state.ready &&
                    <>
                        // content such as material UI icons.
                    </>
               </div>
        )
    }

}

Also, i have imported my icons dynamically as such :
const ArrowBackIosIcon = dynamic(() => import('@material-ui/icons/ArrowBackIos'))

hope it hels!

With Gatsby, I fixed this issue with:

import '@fortawesome/fontawesome-svg-core/styles.css';

This also works in Next.js in April 2021 ! โ™ฅ๏ธ

A quick heads up... Newer versions of Next.js may give you the following error:

Module not found: Package path ./styles.css is not exported from package

Font Awesome's docs recommend importing like this instead:

import '../node_modules/@fortawesome/fontawesome-svg-core/styles.css'

The docs state that this is a temporary workaround.

Source: https://fontawesome.com/v6.0/docs/web/use-with/react/use-with#troubleshooting-with-next-js

Was this page helpful?
0 / 5 - 0 ratings