CSS Tutorial 0/203 lessons ~6 min read Lesson 124

    CSS in React

    css in react css in react spans styled-components, emotion, stylex, vanilla-extract, linaria, and tailwind-in-jsx — staff engineers evaluate based on

    Course progress0%
    Focus
    27 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    CSS in React spans styled-components, Emotion, StyleX, vanilla-extract, Linaria, and Tailwind-in-JSX — staff engineers evaluate based on runtime cost, SSR extraction, token integration, and whether styles are co-located with component logic or generated at build time.

    The React team's rendering model (concurrent features, RSC, streaming) changed which CSS-in-JS libraries remain viable for App Router — runtime injection libraries face explicit trade-offs.

    Business problem

    Business pressure: Product wants themeable components with prop-driven variants — size="lg" intent="danger". Co-locating styles with React components speeds feature delivery but wrong library choice adds 30KB runtime and breaks SSR streaming.

    • DX: Styles beside JSX — fewer context switches.
    • Dynamic UI: Prop-driven variants without maintaining BEM modifier classes manually.
    • RSC boundary: Server Components cannot use runtime CSS-in-JS — architectural fork.

    Why this feature exists

    Platform history: styled-components (2016) popularized tagged template literals in JS. Emotion followed with performance focus. Meta's StyleX and vanilla-extract push compile-time extraction for scale.

    • Problem solved: Global CSS + React component model mismatch.
    • Rejected alternative: CSS Modules only — verbose for dynamic variants.
    • Modern role: Hybrid — RSC + CSS Modules/ Tailwind + client islands with runtime CSS where needed.

    Browser rendering perspective

    Runtime CSS-in-JS: Injects <style> tags on render — blocks or interleaves with React hydration. Compile-time: static CSS files — identical pipeline to Modules.

    • INP risk: Style recalc on every variant mount if library injects per component instance.
    • StyleX/Linaria: Build extracts atomic CSS — no runtime injection.

    Internal browser workflow

    Runtime path: React render → library serializes styles → insert style tag → class assigned. Build path: Babel/Vite plugin extracts CSS at compile → link in document head.

    Feature deep dive

    Categories: Runtime (styled-components, Emotion), Atomic compile-time (StyleX, Linaria), Zero-runtime (vanilla-extract, CSS Modules), Utility (Tailwind className).

    javascript
    // styled-components — runtime
    const Button = styled.button`
    padding: 0.5rem 1rem;
    background: ${props => props.$primary ? 'var(--primary)' : '#fff'};
    `;
    // vanilla-extract — build time
    import { style } from '@vanilla-extract/css';
    export const btn = style({ padding: '0.5rem 1rem' });

    Syntax

    Transient props: $prefix in styled-components avoids DOM attribute leak. css prop Emotion — use sparingly for one-offs.

    Examples

    ThemeProvider token bridge:

    css
    const theme = { colors: { primary: '#4f46e5' } };
    <ThemeProvider theme={theme}>
    <Button $primary>Save</Button>
    </ThemeProvider>

    Real-world use

    Meta uses StyleX on facebook.com surfaces. Discord migrated concerns toward Tailwind. Many Next.js apps dropped runtime styled-components for RSC compatibility — moved to Tailwind or CSS Modules.

    Real production example

    Pattern: RSC layout with CSS Modules; client components use vanilla-extract or Tailwind; ban runtime CSS-in-JS in server components via eslint.

    Enterprise use case

    Enterprise: ADR per app tier — marketing Tailwind, product app CSS Modules + tokens, legacy styled-components quarantined.

    Accessibility considerations

    A11y: Runtime libraries support :focus-visible in template — do not lose pseudo states. Server-rendered class mismatch breaks hydration focus styles.

    Performance considerations

    Performance: Prefer zero-runtime for high-traffic surfaces. Profile React Profiler + Performance panel for style injection during mount storms.

    SEO considerations

    SEO: SSR must extract styles to head for FCP — styled-components SSR APIs; or use static extraction.

    Scalability considerations

    Scale: ThemeProvider at root — changing theme re-renders subtree; use CSS variables + single class toggle on html for scale.

    Common production issues

    Failures: Hydration mismatch when class names differ server/client. RSC import of styled component crashes build.

    Debugging guide

    Debug: Count style tags in head during navigation — growth indicates per-mount injection leak.

    Best practices

    • Zero-runtime for App Router default.
    • Theme via CSS variables on :root.
    • eslint boundaries: no styled in server files.

    Anti-patterns

    • Global styled-components createStyle reset without isolation plan.
    • css prop on every element in hot paths.

    Trade-offs

    • Runtime: dynamic props easy; perf + RSC cost.
    • Compile-time: perf win; less dynamic unless variables.

    Architecture review questions

    • Which components still use runtime CSS-in-JS and why?
    • RSC-compatible styling strategy documented?

    Interview questions

    Why did Next.js App Router complicate styled-components?(Advanced)

    Server Components cannot run client-only style injection. Runtime libraries need client boundary and SSR extraction — streaming RSC prefers static CSS. Teams migrated to compile-time or utility CSS.

    Follow-up: Compare StyleX vs vanilla-extract

    Hands-on exercise

    Exercise: Same button in styled-components vs vanilla-extract — measure client JS and style tag count.

    Staff engineer notes

    • CSS-in-React choice is a React rendering model decision — revisit after RSC adoption.

    Common pitfalls

    • Importing runtime styled in server component.

    Try it yourself

    Edit the CSS panel — the preview updates live. Use DevTools Performance and Accessibility panels to validate.

    Try it yourself

    Preview

    Summary

    CSS in React encompasses runtime and compile-time styling strategies — staff engineers align library choice with RSC boundaries, SSR extraction, and runtime performance budgets.

    Key takeaways

    • CSS-in-React spans runtime and compile-time approaches.
    • RSC pushes zero-runtime and static extraction.
    Ready to mark this lesson complete?Track your journey across the entire course.