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()
}
}
}