18 — Styling Next.js — Global CSS, Modules, Tailwind, Sass, CSS-in-JS
A styling section that lists five valid options used to read as indecision to me. The model that clicked: all five approaches coexist — global CSS for app-wide rules, CSS Modules for locally-scoped styles, Tailwind for utility-first composition, Sass for preprocessing power, and CSS-in-JS for dynamic theming [1][2][3][4][5]. The choice is less "which is correct" and more "which matches the project's conventions" — Tailwind is the modern default for new work.
Global CSS — the app-wide baseline
Global CSS refers to styles applied across the entire application — a single stylesheet whose rules affect every page unless overridden by more specific rules [1]. In the App Router, a globals.css imported into the root layout establishes the baseline: resets, design tokens, base typography. Global CSS is the right place for things that should be truly universal and the wrong place for component-specific styles.
/* app/globals.css — imported once in the root layout */
@tailwind base;
@tailwind components;
@tailwind utilities;
:root { --color-bg: #ffffff; }
body { background: var(--color-bg); }CSS Modules — locally scoped by default
CSS Modules locally scope CSS by generating unique class names, so I can use the same class name in different files without collisions [2]. The scoping is automatic — the build turns .button in Button.module.css into something like .Button_button__a1b2c, guaranteeing it won't leak. This is the conventional choice when a project wants component-scoped styles without a utility framework.
// Button.tsx
import styles from './Button.module.css';
export function Button() {
return <button className={styles.button}>Click</button>;
}Tailwind CSS — utility-first
Tailwind is a utility-first CSS framework: pre-defined utility classes composed directly in markup, instead of writing custom CSS rules [3]. The payoff is rapid UI development and consistent design without context-switching between markup and stylesheets. Tailwind has become the de facto default for new Next.js projects, and create-next-app offers it as a first-class option.
export function Card() {
return <div className="rounded-lg border p-4 shadow-sm">…</div>;
}The trade-off is the class-name density in markup, which some find noisy. The win is that the design system lives in the config and the utilities, not in ad-hoc CSS files that drift.
Sass — preprocessing power
Sass extends CSS with variables, nesting, mixins, and functions, compiled down to standard CSS [4]. Next.js has built-in Sass support once the package is installed, accepting both .scss and .sass extensions, and component-level Sass via .module.scss. Sass earns its keep in large stylesheets where mixins and nesting reduce repetition; for most modern work, Tailwind and CSS custom properties have absorbed much of that need.
CSS-in-JS — dynamic and co-located
CSS-in-JS writes styles in JavaScript files, using libraries that generate CSS at runtime or build time [5]. The benefits are component-level styling, dynamic theming driven by JS values, and easier CSS dependency management. In the App Router, the constraint matters: because Server Components don't run client-side JS, runtime CSS-in-JS doesn't work in them — the supported approaches are the zero-runtime/build-time ones (e.g., the version of styled-components or Panda CSS that extracts at build). CSS-in-JS is now a deliberate choice rather than the default it once was.
How I use this
Tailwind is the default for every new project — the utility-first model, the build-time extraction, and the first-class Next.js integration make it the path of least resistance. Global CSS holds the reset and design tokens. CSS Modules come in when a piece needs scoped styles that don't fit the utility mold. I largely skip Sass (Tailwind covers most of what Sass once solved) and avoid runtime CSS-in-JS in the App Router (Server Components don't run client JS). The principle: pick one primary approach and stick to it; the others are available when a specific need demands them.
References
[1] Vercel, "Global CSS," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/getting-started/css#global-css
[2] Vercel, "CSS Modules," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/getting-started/css#css-modules
[3] Vercel, "Tailwind CSS in Next.js," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/getting-started/css#tailwind-css
[4] Vercel, "How to use Sass in Next.js," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/guides/sass
[5] Vercel, "How to use CSS-in-JS libraries (App Router)," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/guides/css-in-js
[6] Tailwind Labs, "Tailwind CSS," tailwindcss.com, 2024. [Online]. Available: https://tailwindcss.com/
Knowledge check · Question 1 of 5
CSS Modules solve which problem?
Comments
Leave a Comment
You must be signed in to comment
0 Comments
No comments yet. Be the first to comment!