Skip to content
Happy Programming Guide
Start learning
Web Development

Tailwind Not Working in Next.js 15

Classes have no effect, styles vanish in production, or the build fails after upgrading. Tailwind v4 changed the setup completely. The v4 config, the v3 leftovers to remove, and the content-scanning traps.

A close-up of programming code on a screen

Tailwind stopped working in a Next.js project for one of a small number of reasons, and the most common in 2026 is version confusion: Tailwind 4 replaced the entire configuration model, and a project following v3 instructions on a v4 install, or the reverse, gets no styles at all. The rest are the classic causes — the global stylesheet not imported, content paths that miss your files, dynamic class names Tailwind cannot see, and a PostCSS setup left over from before. Check the version first; it decides which of the fixes below apply.

Step 1: which version?#

Terminal
npm ls tailwindcss
cat package.json | grep tailwind

A 4.x version uses the setup in the next section. A 3.x version uses the one after. Mixing them — a tailwind.config.js with content paths and @tailwind base; directives on a v4 install — produces a stylesheet with no utilities in it, silently.

Tailwind 4 with Next.js#

Terminal
npm install tailwindcss @tailwindcss/postcss postcss
JavaScript
// postcss.config.mjs
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};
CSS
/* app/globals.css */
@import "tailwindcss";
JavaScript
// app/layout.js
import './globals.css';

That is the whole setup. No tailwind.config.js, no content array, no @tailwind directives, no autoprefixer (v4 handles prefixing itself). Tailwind 4 finds your source files automatically, ignoring anything in .gitignore. Customisation goes in CSS:

CSS
@import "tailwindcss";

@theme {
  --color-brand: #0f766e;
  --font-display: "Bricolage Grotesque", sans-serif;
}

If you had a v3 project, the official upgrade tool, npx @tailwindcss/upgrade, converts the config and the CSS. Run it on a clean git state and review the diff.

Tailwind 3 with Next.js#

JavaScript
// tailwind.config.js
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx,mdx}',
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: { extend: {} },
  plugins: [],
};
JavaScript
// postcss.config.js
module.exports = { plugins: { tailwindcss: {}, autoprefixer: {} } };
CSS
@tailwind base;
@tailwind components;
@tailwind utilities;

In v3 the content paths are everything. A component in a folder not listed there gets no styles, and the failure is silent. The src line covers projects created with the src directory option; add any other folder you keep components in.

Cause: the stylesheet is not imported#

Whatever the version, the CSS file has to be imported once, in the root layout for the App Router or pages/_app.js for the Pages Router. Importing it in a single page styles that page only. Check the import path is right; a typo gives a build error, but an import in the wrong file gives nothing.

Cause: works in dev, gone in production#

Almost always content scanning. In development Tailwind may be more forgiving; the production build generates only the classes it found in scanned files. Causes:

  • v3: a folder missing from content.
  • v4: source files inside an ignored folder, or generated at build time. Add them explicitly: @source "../node_modules/some-ui-lib"; in the CSS.
  • Classes built by string concatenation, below.
Terminal
rm -rf .next
npm run build

A stale .next cache after a config change can also keep old output around. Delete it and rebuild before investigating further.

Cause: dynamic class names#

JSX
// Tailwind cannot see these classes, so it never generates them
const colour = 'red';
<div className={'bg-' + colour + '-500'} />

// Write the full class names so they appear in the source
const classes = { red: 'bg-red-500', green: 'bg-green-500' };
<div className={classes[colour]} />

Tailwind scans files for complete class strings. A class assembled at runtime does not exist in the source, so it is not in the CSS. Always write complete class names, and choose between them in code.

Cause: a leftover configuration#

After upgrading to v4, a tailwind.config.js in the root is ignored unless referenced with @config, and old @tailwind directives fail. A postcss.config.js still listing tailwindcss as the plugin (rather than @tailwindcss/postcss) errors with a message about using the PostCSS plugin package. Remove the v3 files rather than leaving both around.

Cause: the wrong CSS file wins#

A component library’s CSS imported after globals.css, or a CSS module with the same specificity, can override utilities. Check the element in the browser’s inspector: if the Tailwind class is present in the HTML and the rule is crossed out, it is a cascade problem, not a Tailwind one. If the class is present and no rule exists for it at all, Tailwind did not generate it, and the causes above apply.

Questions people ask#

Should I upgrade to Tailwind 4?

For new projects, yes; it is the default install and the setup is simpler. For existing v3 projects, the upgrade tool does most of the work, but do it as its own change.

Does create-next-app set this up?

Yes, if you choose Tailwind in its prompts; it generates the correct files for the current version. Comparing your project with a fresh one is a quick way to spot differences.

Why do some classes work and others not?

The ones that work were found in scanned files; the ones that do not were either assembled dynamically or live in an unscanned location.

Do I still need autoprefixer?

Not with v4. With v3, yes.

Where to go next#

Tailwind CSS for beginnersRead next

Keep reading

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *