CSS-in-JS vs. CSS Modules

Two ways to stop styles leaking: a .module.css file whose classes the build renames, or styles written inside the component in JS.

styles that can't leakstyles that only apply herescoped stylesstyled componentscss modules vs emotionwhy is my class name a random stringlocal csskeeping styles from bleeding into other components

See it

Live demo coming soon

What it is

Both solve the same old problem: a plain .css file is global, so two people writing .card in different features overwrite each other. CSS Modules keeps the CSS in a real stylesheet (Button.module.css) and lets the build rename every class to something unique like Button_card__x7f2, which you import as an object and read as styles.card. CSS-in-JS (styled-components, Emotion) moves the styles into your component file as tagged templates or objects, generating the class names at runtime.

Pick CSS Modules when you want plain CSS, zero runtime cost, and styles that work no matter where the component renders. Pick CSS-in-JS when styles genuinely depend on props or a theme object and you want them colocated with the logic. If you want prop-driven styling without the runtime, the middle path is zero-runtime CSS-in-JS: vanilla-extract, Linaria, Panda, or StyleX, all of which compile to static CSS at build time.

The current gotcha is runtime CSS-in-JS versus React Server Components and streaming. Those libraries need a client-side context and a style injection step, so the provider and every component importing the styling runtime have to be client components. That is not literally the whole app, but it is the entire branch under that provider, which in practice is most of the interesting part. On top of that you owe extra setup to avoid a flash of unstyled content, and you pay a real cost on every render. In a modern App Router codebase, CSS Modules or a compiled solution is the lower-friction default.

Ask AI for it

Convert this component's global stylesheet to CSS Modules. Create a Component.module.css next to the file, move the rules in unchanged, rename classes to short local names (root, header, isActive), import it as styles and reference styles.root in the markup. Use CSS custom properties for anything that varies with props instead of reaching for a runtime CSS-in-JS library, compose conditional classes with clsx, and delete the now-unused global rules.

You might have meant

utility first cssdesign tokenscomponentreact server componentsshadow dom