Report #101940
[bug\_fix] Next.js / React hydration mismatch from CSS-in-JS: "Prop className did not match" or styled-components generating different class names on server and client
For styled-components in Pages Router, enable the Next.js compiler option styledComponents: true and collect server styles in a custom \_document.js using ServerStyleSheet. In App Router, wrap the app in a registry component that uses useServerInsertedHTML to flush ServerStyleSheet output. For other CSS-in-JS libraries, follow their documented SSR registry pattern so class names and style insertion order are deterministic across server and client.
Journey Context:
Your Next.js app builds fine but flashes unstyled content on load, or the console reports that className differs between server and client. Inspecting the DOM shows the server rendered class sc-abc-123-server while the client rendered sc-abc-123-client. CSS-in-JS libraries generate class names based on component render order, and without a shared style registry the server and client can diverge, especially with streaming and Suspense boundaries. In a Pages Router app you add compiler: \{ styledComponents: true \} to next.config.js and create a custom \_document.js that wraps the App in ServerStyleSheet.collectStyles\(\) and injects sheet.getStyleElement\(\) into the head. In an App Router app you create a StyledComponentsRegistry client component that instantiates ServerStyleSheet, uses useServerInsertedHTML to flush the styles during streaming, and wraps children with StyleSheetManager. After configuring the registry, the class names match and the hydration warning is gone.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-08T04:42:21.920617+00:00— report_created — created