Skip to content
C.W.K.
Stream
Lesson 03 of 08 · published

CSS-in-JS Limitations

~18 min · CSS-in-JS, styled-components, registry

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

Why styled-components and emotion struggle

Both inject styles at runtime via JavaScript. Server Components ship zero JS to the client; runtime CSS-in-JS therefore can't work in a Server Component. The directive boundary becomes a hard wall.

ApproachServer ComponentsClient Components
CSS Modules
Tailwind CSS
styled-components✅ (with registry)
emotion✅ (with registry)

The registry pattern

If you must keep CSS-in-JS, wrap your app in a Client "style registry" that collects styles during server rendering and flushes them into the response. Performance is a tax you pay forever.

The clean answer

For new projects, use Tailwind or CSS Modules. They run everywhere and cost nothing at runtime.

Prefer build-time or static styling for Server Components. If a runtime CSS-in-JS library is required, isolate it behind a Client Component and install the framework's registry pattern at the smallest boundary that can collect server-rendered styles. Adding a registry can make a library render, but it does not restore Server Component benefits inside a client-marked subtree. Theme providers, runtime injection, and hydration work still enlarge the client surface and complicate streaming.

Render the styled page with JavaScript disabled, inspect the initial HTML for styles, and watch for flashes or hydration warnings under streaming. Compare the client bundle and component boundary with a CSS Module or Tailwind version.

Code

styled-components registry·tsx
// lib/StyledComponentsRegistry.tsx
'use client';
import { useState } from 'react';
import { useServerInsertedHTML } from 'next/navigation';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';

export function StyledComponentsRegistry({ children }: { children: React.ReactNode }) {
  const [sheet] = useState(() => new ServerStyleSheet());

  useServerInsertedHTML(() => {
    const styles = sheet.getStyleElement();
    sheet.instance.clearTag();
    return <>{styles}</>;
  });

  return (
    <StyleSheetManager sheet={sheet.instance}>
      {children}
    </StyleSheetManager>
  );
}

External links

Exercise

If your project uses styled-components, set up the registry pattern and verify SSR styles arrive without a flash of unstyled content. If not, write a one-paragraph case for / against introducing it.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.