Styling Options

CSS Modules, Tailwind, CSS-in-JS — A Map

Styling Options

A quick map of the major React styling approaches and when each one fits.

4 min read Level 1/5 #react#styling#css
What you'll learn
  • Recognize the major styling approaches
  • Pick one for a new project

React doesn’t care how you style your components. The ecosystem has a handful of popular options, each with its own trade-offs.

Plain CSS

Just import a CSS file:

// App.jsx
import "./App.css";

function App() {
  return <button className="btn">OK</button>;
}

Simplest possible setup. Class names are global — your problem to keep them organized. Fine for very small projects.

CSS Modules

Locally scoped class names — no global collisions.

// Button.module.css
.btn { padding: 10px; }

// Button.jsx
import styles from "./Button.module.css";
function Button() {
  return <button className={styles.btn}>OK</button>;
}

Vite/Next.js support CSS Modules out of the box. You write normal CSS but get unique class names per file.

Tailwind CSS

Utility-first classes. No CSS files for components — you compose classes in the JSX.

<button className="px-4 py-2 rounded bg-blue-500 text-white hover:bg-blue-600">
  OK
</button>

Pros: very fast to build with, no class-naming questions, automatic purging of unused styles. Cons: classes can pile up; opinionated about visual design.

CSS-in-JS — styled-components / Emotion

Write CSS inside your JS:

import styled from "styled-components";

const Button = styled.button`
  padding: 10px;
  background: ${p => p.kind === "danger" ? "red" : "blue"};
`;

<Button kind="danger">Delete</Button>

Pros: dynamic styles from props feel natural. Cons: runtime cost, and the React Server Components story is awkward.

CSS-in-JS — “Zero-runtime”

Tools like vanilla-extract and Linaria offer the same author experience but compile to real CSS files (no runtime). The current sweet spot for typed CSS without performance trade-offs.

Quick Comparison

ApproachSetupPowerBundle costBest for
Plain CSSNoneLowTinyDemos
CSS ModulesTinyMediumTinyMost apps
TailwindOne configHighTiny (after purge)Speed-focused builds
styled-componentsLibraryHighLargerHighly dynamic styles
vanilla-extractLibraryHighTinyType-safe design systems

Pick One

There’s no objectively right answer. Pick by:

  • What your team knows
  • What your design system requires
  • Whether you’re using a framework with opinions (Next.js works well with all of these)

For a new app on your own: Tailwind for speed, CSS Modules if you want clean separation, vanilla-extract if you’re TypeScript-heavy.

Up Next

Forms get complicated. A library helps.

Forms Library →