Add styles three ways — global CSS, Tailwind utility classes, and locally scoped CSS Modules — and know when to use each.
Why: a global stylesheet applies everywhere. Import it once in the root layout. Keep global CSS for truly app-wide things (resets, base styles); scope the rest so styles don’t leak between pages.
/* app/globals.css */
body {
margin: 0;
font-family: system-ui, sans-serif;
}
/* app/layout.tsx */
import './globals.css'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}Why: Tailwind lets you style with small utility classes right in your markup — no separate CSS file per component. Install it, register the PostCSS plugin, and import it once. Note: PostCSS is the tool that processes your CSS at build time.
$ pnpm add -D tailwindcss @tailwindcss/postcss# postcss.config.mjs
export default {
plugins: {
'@tailwindcss/postcss': {},
},
}
# In app/globals.css
@import 'tailwindcss';Why: once imported, style elements by composing utility classes in className. Each class does one thing (padding, color, flex), so you build designs without leaving your component.
export default function Page() {
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24">
<h1 className="text-4xl font-bold text-blue-600">Welcome to Next.js!</h1>
</main>
)
}Why: when you want plain CSS that can’t collide with other components, use a .module.css file. Class names are made unique automatically, so .title here never clashes with a .title elsewhere. Import it as an object and read class names off it.
/* app/blog/blog.module.css */
.title {
font-size: 2rem;
color: rebeccapurple;
}
/* app/blog/page.tsx */
import styles from './blog.module.css'
export default function Page() {
return <h1 className={styles.title}>The Blog</h1>
}