Using CSS-in-JS in Next.js – Style Registries, Streaming Support, and Concurrent Rendering

CSS-in-JS libraries allow you to define styles directly inside your React components. In Next.js, using these libraries with Server Components and streaming requires support for React 18’s concurrent rendering. This article explains how to configure styled-jsx and styled-components using style registries and the useServerInsertedHTML hook.

CSS-in-JSStyle registrystyled-jsxstyled-components

~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:

  1. Create a style registry to collect styles during rendering
  2. Use useServerInsertedHTML to inject styles before content
  3. 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