CSS Modules & Scoped Styles
Problem
CSS class names collide across components, causing button styles to leak into cards or typography changes to affect unrelated pages. Developers resort to increasingly specific selectors or !important to override conflicts, making stylesheets unmaintainable and fragile.
Solution
Automatically scope CSS class names to specific components by generating unique identifiers at build time. This prevents style collisions and eliminates naming conflicts without requiring manual conventions.
Example
This example demonstrates CSS Modules which automatically scope class names to prevent style collisions between components.
/* Button.module.css - Styles scoped to Button component only */
.button {
background: blue; /* Won't affect other components with .button class */
padding: 10px;
}
// Import styles object with scoped class names
import styles from './Button.module.css';
// className becomes something like "Button_button__a1b2c3" at runtime
<button className={styles.button}>Click me</button>
Benefits
- Prevents style collisions by automatically scoping class names.
- Eliminates need for strict naming conventions like BEM.
- Works with standard CSS without learning new syntax.
- Build-time scoping has zero runtime performance cost.
- Still allows global styles when explicitly needed.
Tradeoffs
- Generated class names make debugging harder without source maps.
- Sharing styles between components requires explicit composition.
- Cannot dynamically compute styles based on props.
- Requires build tool configuration and support.
- May complicate integration with third-party CSS frameworks.