Frontend Patterns

Pattern

CSS Modules & Scoped Styles

Scope CSS automatically to specific components to prevent global style conflicts.

Styling Beginner

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.
Stay Updated

Get New Patterns
in Your Inbox

Join thousands of developers receiving weekly insights on frontend architecture patterns

No spam. Unsubscribe anytime.