
Next.js Installing Tailwind CSS v3
This project runs Tailwind CSS 4, which is the version the official Next.js "getting started" docs point you toward by default now — so it's worth being upfront about why an article on installing an older major version still earns a place in this series. Tailwind 4 rebuilt its engine around modern CSS features — native cascade layers, the @property at-rule for animatable custom properties, color-mix() for opacity handling — and those features simply don't exist in older browsers. If your product's analytics show a meaningful slice of traffic on genuinely old browser versions, or you're maintaining a codebase that predates Tailwind 4 and haven't yet had a reason to migrate, Tailwind 3 remains a fully supported, actively documented path in Next.js specifically for that broader compatibility.
Installing it
Tailwind 3's setup is the classic pattern most people who've used Tailwind for any length of time already recognize — install the package plus its PostCSS peer dependencies, then run init to scaffold both config files at once:
npm install -D tailwindcss@^3 postcss autoprefixer
npx tailwindcss init -p
The -p flag is doing real, easy-to-miss work here — it's what generates postcss.config.js alongside tailwind.config.js in one command, rather than leaving you to hand-write the PostCSS config yourself afterward. Skip it, and Tailwind's directives won't actually get processed at all, which tends to surface as "none of my utility classes are doing anything" with no obvious error pointing at the missing PostCSS wiring as the actual cause.
Configuring the content paths
Tailwind 3 scans your source files at build time to determine which utility classes are actually used, so it can purge everything else — the content array in tailwind.config.js is what tells it exactly where to look:
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {},
},
plugins: [],
};
Getting this glob pattern wrong is a genuinely common source of "Tailwind classes just aren't working" confusion, and it's worth understanding precisely why: a class you reference only in a file outside these patterns is invisible to Tailwind's scanner, so it gets purged from the final build entirely, even though your JSX looks perfectly correct and the class name is spelled right. If you add a new top-level directory for components — outside app/, pages/, or components/ — and styles mysteriously stop applying there, this content array not including that new path is the first thing worth checking, before assuming anything else is broken.
Adding the Tailwind directives
Three @tailwind directives go into your global stylesheet, and they correspond to Tailwind's own internal layer system — base resets, component-level classes, and the utility classes you'll actually be using constantly:
/* app/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
And that stylesheet gets imported once, in the root layout:
// app/layout.tsx
import "./globals.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
This single import at the root is genuinely sufficient — there's no need to re-import globals.css in every page or nested layout; the App Router only needs it declared once, at the top of the tree, for the styles to apply globally across every route beneath it.
Using it
With setup complete, utility classes work exactly as documented anywhere else in the Tailwind ecosystem — nothing about the App Router changes how you actually write Tailwind class strings day to day:
export default function Page() {
return <h1 className="text-3xl font-bold underline">Hello, Next.js!</h1>;
}
Turbopack support
Worth confirming explicitly since it's the kind of thing people reasonably worry about when pairing an older CSS tooling major version with Next.js's newer, faster bundler: Tailwind CSS and PostCSS have been supported under Turbopack since Next.js 13.1 — there's no special configuration or compatibility shim required specifically because you're on Tailwind 3 rather than 4. If you're running Turbopack (the default dev bundler in this version of Next.js), this setup works precisely as written above, with no extra steps.
Deciding between Tailwind 3 and 4 for a new project
Given this project itself runs Tailwind 4, it's worth being direct about when 3 is genuinely still the right call versus when it's just inertia.
Stay on or choose Tailwind 3 when: your actual, measured traffic includes a meaningful share of older browsers that don't support the modern CSS features Tailwind 4's engine leans on; you're maintaining an existing codebase already built on Tailwind 3 with plugins or configuration that haven't been verified against 4's changes; or you depend on a component library or design system still built and tested specifically against Tailwind 3's conventions.
Move to Tailwind 4 when: you're starting a genuinely new project with no existing Tailwind investment to preserve (which is what this project itself did); your actual audience skews toward current browser versions, making the modern-CSS-feature requirement a non-issue in practice; or you specifically want Tailwind 4's simplified, CSS-first configuration model over the JavaScript-config-file approach Tailwind 3 uses.
They are not a security-relevant or urgent-upgrade situation the way, say, an outdated Next.js major version might be — Tailwind 3 remains fully maintained, documented, and supported as a first-class path in the framework specifically because "I need broader browser support" is a legitimate, ongoing reason to choose it deliberately, not a compatibility shim being kept around only for legacy projects that haven't gotten around to migrating yet.
Key Takeaways
| Step | Command / File |
|---|---|
| Install | npm install -D tailwindcss@^3 postcss autoprefixer |
| Scaffold config | npx tailwindcss init -p (the -p generates postcss.config.js too) |
| Tell Tailwind where to scan | content array in tailwind.config.js |
| Enable the utility classes | Three @tailwind directives in your global CSS |
| Wire it into the app | Import the global CSS once, in the root layout |
| Turbopack compatibility | Supported since Next.js 13.1 — no extra config needed |
The choice between Tailwind 3 and 4 in a Next.js project isn't really a "which is better" question — it's a browser-support and existing-investment question, and Next.js keeps first-class, actively maintained documentation for both precisely because both answers are legitimate depending on who's actually visiting your site and what you're already maintaining.


