Styling Options Overview
Unlike some frameworks that ship with one blessed way to write CSS, Next.js is deliberately unopinionated about styling. The App Router supports several approaches out of the box, and mixing more than one within a single project is common and fully supported — a marketing page might use Tailwind while a design-system-heavy dashboard uses CSS Modules or CSS-in-JS.
Comparing the main approaches
Approach | Pros | Cons |
|---|---|---|
Global CSS | Simplest possible setup; familiar to anyone who knows CSS | No scoping — class names can collide as the app grows; only importable from the root layout |
CSS Modules | Automatic class-name scoping with zero extra config; plain CSS syntax | One file per component to manage; no shared design tokens without a convention |
Tailwind CSS | Extremely fast iteration once learned; consistent design tokens via config; small production CSS via purging | Verbose class lists in markup; a learning curve for utility-class syntax |
CSS-in-JS (Emotion, styled-components) | Colocates styles with components; dynamic styles driven by props/theme | Runtime libraries need extra App Router configuration and force affected components to be Client Components |
Sass / SCSS | Variables, nesting, and mixins on top of familiar CSS syntax | Adds a preprocessing step; still lacks automatic scoping unless paired with modules |
How they combine in practice
Global CSS is almost always used for resets, CSS variables/design tokens, and truly app-wide base styles.
CSS Modules or Tailwind typically handle component- and page-level styling day to day.
CSS-in-JS shows up when a component library (like MUI, used on this very site) is built around it, or when styles must react to runtime state.
Sass can layer on top of Global CSS or CSS Modules (
.module.scss) when a team already relies on its features.
The following pages go through Global CSS, CSS Modules, Tailwind CSS, and CSS-in-JS individually, with the specific App Router rules and gotchas for each.