Features
- Locally scoped class names prevent collisions
- Composable styles with composes keyword
- Standard CSS syntax — no new language to learn
- Built-in support in most bundlers and frameworks
- Works with preprocessors (Sass, Less, PostCSS)
Pros
- Zero learning curve — just CSS with scoping
- Built into Next.js, Vite, webpack out of the box
- No runtime overhead — plain CSS output
- Easy to adopt incrementally in existing projects
Cons
- No dynamic styles based on props
- Class name composition can become verbose
- TypeScript type generation requires extra tooling
Overview
CSS Modules is a CSS file convention where all class names are locally scoped by default. When you import a CSS Module, each class name is transformed into a unique identifier, preventing naming collisions across your application without any runtime cost.
CSS Modules use standard CSS syntax — there’s no new language or API to learn. The key difference is that class names are treated as local by default, and you import them as a JavaScript object. Most modern build tools (Vite, webpack, Next.js) support CSS Modules out of the box with no additional configuration.
When to Use
CSS Modules are the right choice when you want scoped styles without a CSS-in-JS runtime, when your team is comfortable with traditional CSS, or when you need a simple, zero-config styling solution. They work well for projects that don’t need dynamic style generation or a utility-class approach.
Getting Started
/* Button.module.css */
.button {
background-color: blue;
color: white;
padding: 8px 16px;
border-radius: 4px;
}
.button:hover {
background-color: darkblue;
}
import styles from "./Button.module.css";
function Button() {
return <button className={styles.button}>Click me</button>;
}