Styling is a main part of any website. CSS Modules provides a great way to write scoped, maintainable CSS in Next.js. Unlike traditional global CSS, which applies styles to the entire project, CSS Modules allow you to style components individually without worrying about name conflict in the whole project.
In this guide, you are going to learn:
So, Let’s dive in!
CSS Modules locally scope css by automatically creating a unique class name.Now, all class names are accordingly scoped to the specific component they are used in. This thing prevents style conflicts and makes styling more predictable.
If you don’t have a Next.js project yet, create one using:
1
2
npx create-next-app@latest my-next-app
cd my-next-app
By default, Next.js supports CSS Modules right away. You just need to follow the correct file naming convention:
For Example, Lets Style a Component with CSS Modules,
# Create a CSS Module file:
Create a new file called Button.module.css inside the styles/ folder (or next to your component).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* styles/Button.module.css */
.button {
background-color: #0070f3;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: background 0.3s;
}
.button:hover {
background-color: #005bb5;
}
# Import and use it in a component:
1
2
3
4
5
6
7
// components/Button.js
import styles from '../styles/Button.module.css';
export default function Button() {
return <button className={styles.button}>Click Me</button>;
}
Now, when you use <Button /> in your project, it will have its own saperate styles!
Sometimes, you may need to apply styles dynamically (e.g., based on props or state). You can do this using template literals with classNames.
For Example, Lets add dynamic classes
1
2
3
4
5
6
7
8
9
import styles from '../styles/Button.module.css';
export default function Button({ primary }) {
return (
<button className={primary ? styles.primaryButton : styles.secondaryButton}>
Click Me
</button>
);
}
# Update Button.module.css with multiple styles:
1
2
3
4
5
6
7
8
9
.primaryButton {
background-color: #0070f3;
color: white;
}
.secondaryButton {
background-color: grey;
color: black;
}
Now you can use <Button primary={true} /> or <Button primary={false} /> to change styles dynamically.
If you need to apply multiple class names, you can use the classnames package:
Install classnames
1
npm install classnames
Use it in your component:
1
2
3
4
5
6
7
8
9
10
11
import styles from '../styles/Button.module.css';
import cx from 'classnames';
export default function Button({ primary }) {
return (
<button className={cx(styles.button, { [styles.primary]: primary })}>
Click Me
</button>
);
}
This way, styles.button is always applied, and styles.primary is applied only if primary is true.
CSS Modules are scoped by default, but if you need global styles (like for a reset or utility classes), you can use a global CSS file inside the styles/ folder.
For Example, Let's add Global CSS,
1. Create a styles/globals.css file:
1
2
3
4
5
6
7
/* styles/globals.css */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background: #f5f5f5;
}
2. Import it inside _app.js:
1
2
3
4
5
6
7
// pages/_app.js
import '../styles/globals.css';
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
Now the styles in globals.css apply to the whole application.
Can I use Tailwind CSS with CSS Modules in Next.js?
Yes absolutely, You can combine Tailwind CSS for utility-based styling and CSS Modules for component-specific styles that make a perfect combo.
Do CSS Modules work with TypeScript?
Should I use CSS Modules or Styled Components?
CSS Modules in Next.js provide a simple, scalable, and conflict-free way to style your components in next.js. Whether you’re working on a small project or a large-scale application, they help keep your styles modular and maintainable.
So, start using CSS Modules today and keep your styles clean, isolated, and bug-free today!