~3 min read • Updated Oct 26, 2025
Introduction
CSS-in-JS libraries let you define styles directly inside your React components. In Next.js, using these libraries with Server Components and streaming requires compatibility with React 18’s concurrent rendering model.
Supported Libraries
The following libraries are supported in Client Components within the app directory:
- ant-design
- chakra-ui
- @fluentui/react-components
- kuma-ui
- @mui/material
- @mui/joy
- pandacss
- styled-jsx
- styled-components
- stylex
- tamagui
- tss-react
- vanilla-extract
emotion is currently working on support.
Three-Step Configuration
To use CSS-in-JS with Server Components and streaming, follow these steps:
- Create a style registry to collect styles during rendering
- Use
useServerInsertedHTMLto inject styles before content - Wrap your app with the registry in a top-level Client Component
Using styled-jsx
Step 1: Create the registry
// app/registry.tsx
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
export default function StyledJsxRegistry({ children }) {
const [jsxStyleRegistry] = useState(() => createStyleRegistry())
useServerInsertedHTML(() => {
const styles = jsxStyleRegistry.styles()
jsxStyleRegistry.flush()
return <>{styles}</>
})
return <StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
}Step 2: Wrap your layout
// app/layout.tsx
import StyledJsxRegistry from './registry'
export default function RootLayout({ children }) {
return (
<html>
<body>
<StyledJsxRegistry>{children}</StyledJsxRegistry>
</body>
</html>
)
}Using styled-components
Step 1: Enable in next.config.js
// next.config.js
module.exports = {
compiler: {
styledComponents: true,
},
}Step 2: Create the registry
// lib/registry.tsx
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
export default function StyledComponentsRegistry({ children }) {
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return <>{styles}</>
})
if (typeof window !== 'undefined') return <>{children}</>
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
}Step 3: Wrap your layout
// app/layout.tsx
import StyledComponentsRegistry from './lib/registry'
export default function RootLayout({ children }) {
return (
<html>
<body>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</body>
</html>
)
}Good to Know
- During SSR, styles are extracted and flushed into the
<head>tag - During streaming, styles from each chunk are appended to existing styles
- Client Component registries avoid re-generating styles on subsequent renders
- For advanced configuration, refer to the Next.js styled-components API reference
Conclusion
CSS-in-JS libraries in Next.js offer powerful styling capabilities. With proper registry setup and useServerInsertedHTML, you can safely use them alongside Server Components and streaming for modern, scalable applications.
Written & researched by Dr. Shahin Siami