React is unopinionated about styling, so the ecosystem offers several approaches, each with different trade-offs in scoping, authoring experience, performance, and how they interact with modern features like Server Components. The main options are plain CSS, CSS Modules, utility-first frameworks like Tailwind, and CSS-in-JS libraries. Choosing well affects maintainability and performance across a whole codebase.
The central problem any approach must solve is scope: global CSS leaks, with class names colliding across a large app. CSS Modules solve this by locally scoping class names per file; Tailwind sidesteps it with composable utility classes; and CSS-in-JS scopes styles to components in JavaScript. Each makes different bets about where styling logic should live and how it is delivered.
This lesson surveys the main styling approaches, their strengths and weaknesses, and considerations for React 19 and Server Components — notably that some runtime CSS-in-JS libraries have friction with server rendering. The goal is to understand the landscape well enough to choose an approach suited to a given project rather than following fashion.