Search code examples
next.jsstyled-components

Styles take time to load - Next.js


When I enter my portfolio it loads the unstyled html page, and only after a few seconds the styles load. How can I resolve this?

NOTE: I'm using Styled-Components

  1. When I enter the page: enter image description here

  2. After a few seconds: enter image description here

I tried looking for styled components compatibility with next.js but couldn't find anything about this bug


Solution

  • Being a CSS-in-JS styling solution, styled-components is geared for client-side rendering, it normally assumes that it's executing in a browser and so it produces CSS styles as a result of JavaScript execution and injects them directly into the document. In this case, since Next.js pre-renders all pages by default, you need to have the CSS styles in the server-side rendered HTML to avoid the flash of unstyled content on first render.

    You can do so following these steps:

    If you are using Next.js 12+ (with SWC compiler):

    Modify next.config.js:

    /** @type {import('next').NextConfig} */
    
    const nextConfig = {
      // ...rest of options
      compiler: {
        styledComponents: true,
      },
    }
    
    module.exports = nextConfig
    

    Create a custom _document.js file on pages folder and add:

    import Document from 'next/document'
    import { ServerStyleSheet } from 'styled-components'
    
    export default class MyDocument extends Document {
      static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet()
        const originalRenderPage = ctx.renderPage
    
        try {
          ctx.renderPage = () =>
            originalRenderPage({
              enhanceApp: (App) => (props) =>
                sheet.collectStyles(<App {...props} />),
            })
    
          const initialProps = await Document.getInitialProps(ctx)
          return {
            ...initialProps,
            styles: [initialProps.styles, sheet.getStyleElement()],
          }
        } finally {
          sheet.seal()
        }
      }
    }