Type something to search...
Next.js Installing Tailwind CSS v3

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

StepCommand / File
Installnpm install -D tailwindcss@^3 postcss autoprefixer
Scaffold confignpx tailwindcss init -p (the -p generates postcss.config.js too)
Tell Tailwind where to scancontent array in tailwind.config.js
Enable the utility classesThree @tailwind directives in your global CSS
Wire it into the appImport the global CSS once, in the root layout
Turbopack compatibilitySupported 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.

Tags :
Share :

Related Posts

Can Next.js Be Used with GraphQL?

Can Next.js Be Used with GraphQL?

Next.js and GraphQL are two powerful technologies that have gained significant traction in the web development community. Next.js, a React-based fram

Dive Deeper
How does Next.js differ from Create React App?

How does Next.js differ from Create React App?

In the world of modern web development, React.js has emerged as a dominant force due to its flexibility, performance, and extensive ecosystem. Two po

Dive Deeper
How does Next.js handle image optimization?

How does Next.js handle image optimization?

In modern web development, image optimization plays a critical role in enhancing user experience and improving site performance. Large, unoptimized i

Dive Deeper