NextjsCSS Modules

CSS Modules

CSS Modules solve the biggest weakness of Global CSS — name collisions — with a simple naming convention: any file named *.module.css gets its class names automatically scoped to the component that imports it. No configuration, no plugin to install; it works out of the box in every Next.js app.
A worked example

components/Button.module.css

CSS
.button {
  padding: 8px 16px;
  border-radius: 6px;
  border: none;
  background-color: #0070f3;
  color: white;
  font-weight: 600;
  cursor: pointer;
}

.button:hover {
  background-color: #0059c1;
}

.secondary {
  background-color: transparent;
  color: #0070f3;
  border: 1px solid #0070f3;
}

components/Button.tsx

TSX
import styles from './Button.module.css'

export default function Button({
  children,
  variant = 'primary',
}: {
  children: React.ReactNode
  variant?: 'primary' | 'secondary'
}) {
  return (
    <button
      type="button"
      className={variant === 'secondary' ? styles.secondary : styles.button}
    >
      {children}
    </button>
  )
}
At build time, Next.js rewrites .button into something unique like Button_button__x8f2a, and the imported styles object maps the original name to that generated one. Two components can each define a class called .button in their own module without any risk of one overriding the other.
Composing classes and using clsx
Because styles.button is just a string, combining conditional classes works the same way it would with any other CSS approach — template literals or a small utility library both work fine.

TSX
import styles from './Card.module.css'

export default function Card({ highlighted }: { highlighted?: boolean }) {
  return (
    <div className={`${styles.card} ${highlighted ? styles.highlighted : ''}`}>
      Card content
    </div>
  )
}
Note
CSS Modules work in both Server and Client Components — importing a .module.css file doesn't require 'use client'. The class-name rewriting happens entirely at build time, so there's no runtime cost and no client-side JavaScript involved.
Tip
CSS Modules also support composes, letting one class inherit the rules of another defined in the same or a different module — useful for a small set of shared base styles without reaching for Sass.
  • Any file ending in .module.css gets its class names automatically scoped — no extra config required.

  • Import it as an object (styles) and reference class names as properties (styles.button).

  • Two components can reuse the same class name in their own modules with zero collision risk.

  • Works in both Server and Client Components since the scoping happens at build time, not runtime.