reactjsgatsbyserver-side-renderingemotionfouc

Flash of Unstyled Content (FOUC) when using gatsby with Emotion?


I'm trying to add Emotion to an existing Gatsby static site. It's generally working great except that the server render doesn't actually render the styles. For a brief moment after loading, or forever if you have JavaScript disabled, only one .js file of global styles is visible.

I've tried the steps in https://www.gatsbyjs.org/docs/troubleshooting-common-errors around clearing the cache, making sure the modules are installed, and updating package versions to latest. No luck.

Is this a known issue that can be dealt with?

You can see the full repository at https://github.com/JoshuaKGoldberg/Goldblog/tree/945d0ca8501b3aa069ef44145e4d05daa35da505.


Solution

  • You're using @emotion/core, which uses the css prop, but you're passing your style tokens to the className prop, which is how you would do it if you're using the emotion package that requires additional setup for server-side rendering to work. See this page in the documentation for a comparison and more details.

    The fix is to first remove your css() function calls around your style object literals:

    // replace this
    export const header = css({
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        flexDirection: "row",
        flexWrap: "wrap",
        marginTop: "1.5rem",
    });
    
    // with this
    export const header = {
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      flexDirection: "row",
      flexWrap: "wrap",
      marginTop: "1.5rem",
    }
    

    Then replace className with css anywhere you're passing in an object or array that you want to work with Emotion:

    // replace this
    <header className={styles.header}>
      <h1 className={styles.heading}>
        <Link className={styles.headingLink} to={`/`}>
          {title}
        </Link>
      </h1>
      <Bio />
    </header>
    
    // with this
    <header css={styles.header}>
      <h1 css={styles.heading}>
        <Link css={styles.headingLink} to={`/`}>
          {title}
        </Link>
      </h1>
      <Bio />
    </header>