Report #86867
[bug\_fix] CSS-in-JS libraries \(styled-components, Emotion\) causing Flash of Unstyled Content \(FOUC\) or hydration className mismatches in Next.js App Router
Implement a registry component using ServerStyleSheet \(for styled-components\) or CacheProvider \(for Emotion\) that collects critical CSS during SSR and injects it into the document head before hydration
Journey Context:
You migrate from Next.js Pages Router to App Router and notice that your styled-components styles are missing during the initial server render, causing a jarring Flash of Unstyled Content where HTML appears as unstyled text before snapping into styled buttons and layouts. The browser console shows warnings about className mismatches between server and client. You check your \_document.js from the old Pages Router setup and realize that the ServerStyleSheet extraction logic you had there doesn't exist in the App Router architecture. Searching the Next.js documentation, you discover that App Router requires a different approach: creating a registry.tsx file that imports styled-components, creates a ServerStyleSheet instance in the render pass, and uses the styled-components sheet to collect all CSS generated during the server render. This registry must be wrapped around the children in your root layout.tsx. The registry uses the 'use client' directive since it needs to access the DOM to inject styles, but it runs during SSR to collect the CSS. The collected styles are then inserted into the document head using the sheet.getStyleElement\(\) method \(or the new styled-components API for React 18 streaming\). This ensures that when the browser receives the HTML, it also receives the critical CSS in a style tag, preventing the FOUC and eliminating the className mismatch because the server and client both use the same styled-components generated classNames extracted during the SSR pass.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T04:23:39.980282+00:00— report_created — created