CSS Modules vs Tailwind CSS in React

Compare CSS Modules and Tailwind CSS for React. See how scoped CSS files and utility classes style the same card, then pick the fit for your team.

6 min read

CSS Modules scope plain CSS to a single component, while Tailwind CSS styles components through small utility classes written directly in the JSX. One keeps styles in separate files, the other moves them into the markup. The right choice depends on how much raw CSS you want to write and how fast you need a consistent design.

The difference at a glance

CSS ModulesTailwind CSS
Styles live in.module.css filesClass names in JSX
ScopingAutomatic per fileReusable utilities
Learning curvePlain CSSNew class vocabulary
OutputOnly imported CSSOnly used utilities
Extra toolingNone in ViteVite or PostCSS plugin

The table is the whole decision in miniature. CSS Modules add scoping to CSS you already know, while Tailwind asks you to learn utility names and gives speed in return.

CSS Modules: scoped CSS files

A CSS Module is a normal CSS file with a .module.css suffix. Vite turns every class in it into a unique name, so the same class name can safely appear in several files.

csscss
/* Card.module.css */
.card {
  padding: 16px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

The component imports the file and reads a class name from the returned object. Vite scopes every class automatically because the file name ends in .module.css.

App.jsxApp.jsx
import styles from "./Card.module.css";
 
function Card() {
  return <div className={styles.card}>A card with scoped styles.</div>;
}

The browser applies the same padding, radius, and shadow as any plain CSS card. The difference is invisible to users but important to maintainers: the class name is unique to this component, so it cannot leak into another one.

Tailwind: utility classes in JSX

Tailwind skips separate CSS files for component styles and uses utility classes that each set one property. The same card is written entirely in the JSX.

App.jsxApp.jsx
function Card() {
  return (
    <div className="rounded-lg p-4 shadow-md">
      A card styled with utility classes.
    </div>
  );
}

Each class maps to a small CSS rule that Tailwind generates at build time. rounded-lg sets the radius, p-4 sets the padding, and shadow-md sets the shadow, and the final stylesheet contains only the utilities your code actually uses.

How each approach handles change

Both approaches handle responsive and state styles, just through different syntax. CSS Modules write media queries and pseudo-classes in the CSS file, while Tailwind adds prefixed variants such as hover: and md: to a class.

For example, a card that grows on wider screens uses a media query in CSS Modules and a md: prefix in Tailwind. The mechanics of breakpoints are the same, so the same mobile-first rules apply to both syntaxes.

Which should you use

  • Choose CSS Modules when you want to keep writing CSS and only need scoping.
  • Choose Tailwind when you want speed, consistency, and fewer naming decisions.
  • Choose CSS Modules when designers hand you CSS to translate directly.
  • Choose Tailwind when the team moves fast and reuses a shared set of utilities.

There is no performance winner in practice. Both compile to static CSS, so decide on workflow and how much of the styling language you want to own.

One common confusion

People often treat the two as rivals and forget they can coexist. A project can use CSS Modules for complex page components and Tailwind utilities for spacing and layout in the same app.

The broader view of where each fits among every styling option is in how to style React components, and the full setup steps are in the Tailwind walkthrough.

Rune AI

Rune AI

Key Insights

  • CSS Modules scope plain CSS to one component per file.
  • Tailwind styles components with small utility classes in JSX.
  • CSS Modules ship only the CSS you import, Tailwind only the utilities you use.
  • Both work in Vite with little or no configuration.
  • They can be combined in one project.
RunePowered by Rune AI

Frequently Asked Questions

Do CSS Modules need a plugin in Vite?

No. Vite treats any file ending in .module.css as a CSS Module and returns a class name object from the import, with no extra package.

Does Tailwind replace all my CSS?

No. Tailwind is utility classes, but you can still write custom CSS alongside it and use the @apply or @utility directives when you need a reusable style.

Which is better for a beginner?

CSS Modules feel closer to plain CSS, so they are easier to start with. Tailwind has a class name vocabulary to learn, but it removes the work of naming and scoping classes.

Conclusion

CSS Modules and Tailwind CSS solve the same problem from opposite directions. CSS Modules scope plain CSS per file, while Tailwind moves small utility classes into the markup, and the better fit depends on how much raw CSS you want to write.