CSS-in-JS means writing styles in JavaScript, next to your components. Its benefits:
- Styles are scoped automatically.
- Styles sit next to the component (colocation).
- Unused styles disappear when you delete the component.
- Styles can use props and theme values directly.
Runtime libraries, such as styled-components and Emotion, create and inject styles while components render. That has costs:
- more JavaScript in the bundle
- work on every render
- extra effort for server rendering
They struggle with React Server Components (RSC) because of how they work. They rely on React context for theming and on client-side hooks to inject styles. Server Components run only on the server, and they can't use context or those hooks. So these styled components must become client components, which loses much of the RSC benefit.
Zero-runtime options, such as vanilla-extract, Linaria or Panda CSS, extract static CSS at build time. You keep the same way of writing styles, without the runtime cost. CSS Modules and Tailwind work with Server Components for the same reason: their CSS is static.
- CSS-in-JS gives scoping, colocation and styles driven by props.
- Runtime libraries add bundle size and inject styles during render.
- They depend on context and client hooks, so they don't work in Server Components.
- Zero-runtime libraries extract static CSS at build time instead.