Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
  1. Home
  2. Blog
  3. Next.js and Tailwind CSS
  4. Tailwind v4 Nextjs 16 Setup: Config, Fonts and 5 Fixes
Auf Deutsch lesen
  1. Blog
  2. Next.js and Tailwind CSS
  3. Tailwind v4 Nextjs 16 Setup: Config, Fonts and 5 Fixes
Next.js and Tailwind CSS
Next.js and Tailwind CSS

Tailwind v4 Nextjs 16 Setup: Config, Fonts and 5 Fixes

SR
Serban Rusu · Founder of Wingo UI
Nov 6, 2026 · 9 min read

On this page

0%
  1. What does a Tailwind v4 setup in Next.js 16 need?
  2. How do I install Tailwind v4 in Next.js?
    1. New app: let create-next-app write it
    2. Existing app: install Tailwind v4 with PostCSS
  3. Where does the Tailwind v4 config go in Next.js?
  4. How do I use next/font with Tailwind v4?
  5. Why is Tailwind v4 not working in Next.js?
    1. 1. "It looks like you're trying to use tailwindcss directly as a PostCSS plugin"
    2. 2. tailwind.config.js changes do nothing
    3. 3. Some classes are missing or lose to other CSS
    4. 4. dark: classes ignore the theme toggle
    5. 5. New classes appear only after a restart
  6. How do I add components on top of this setup?
  7. What do the final files look like?
  8. Next step
  9. FAQ
    1. Does Tailwind v4 need a tailwind.config.js in Next.js?
    2. Should I use @tailwindcss/postcss or @tailwindcss/turbopack?
    3. Why are my Tailwind classes not applied in Next.js?
    4. Do I still need autoprefixer with Tailwind v4?
    5. Which browsers does Tailwind v4 support?

TL;DR

Tailwind v4 in Next.js 16 needs two packages (tailwindcss and @tailwindcss/postcss), a postcss.config.mjs with the plugin, @import "tailwindcss"; at the top of app/globals.css and that file imported once in the root layout. There is no tailwind.config.js and no content array: theme values live in @theme blocks in the CSS, and next/font variables plug in through @theme inline. Since create-next-app 16.4.0 (October 6, 2026) a new app gets the @tailwindcss/turbopack loader in next.config.ts instead of PostCSS: both work under Turbopack, only PostCSS also works with webpack.

Published Nov 6, 2026

You want Tailwind v4 in a Next.js 16 app and the guides disagree: one says postcss.config.mjs, a fresh create-next-app writes something else, and your old tailwind.config.js does nothing. This Tailwind v4 Nextjs guide sets it up from scratch, explains what each line does, wires next/font into the theme, and fixes the five errors that make Tailwind v4 look like it is not working.

What we checked on November 6, 2026: the templates inside create-next-app 16.4.5 (published November 3), the Next.js 16 docs that ship in node_modules/next/dist/docs, Tailwind's own Next.js guide, and the CSS that Tailwind 4.3.3 compiles for every snippet below. This site, wingo-ui.com, runs Next.js 16.3 with Tailwind 4.3.3 and the PostCSS plugin.

What does a Tailwind v4 setup in Next.js 16 need?

Four things, fewer than v3 needed. A Tailwind v4 Nextjs 16 setup is complete with:

  • two dev dependencies: tailwindcss and a bundler integration (@tailwindcss/postcss or @tailwindcss/turbopack),
  • one config entry that registers the integration,
  • @import "tailwindcss"; at the top of app/globals.css,
  • import "./globals.css" in app/layout.tsx.

What is gone: tailwind.config.js, the content array, the three @tailwind directives, autoprefixer and postcss-import. Tailwind v4 finds your class names by scanning the project (it skips node_modules and anything in .gitignore), adds vendor prefixes itself, and reads the theme from CSS.

How do I install Tailwind v4 in Next.js?

Let create-next-app write the setup for a new app. An existing app takes four small edits with the PostCSS plugin.

New app: let create-next-app write it

bash
npx create-next-app@latest my-app --yes
cd my-app

--yes takes your saved preferences or the defaults, which include TypeScript, ESLint, the App Router, the @/* alias and Tailwind. Since version 16.4.0 (October 6, 2026) the Tailwind part changed. We read the 16.4.5 templates: when the bundler is Turbopack, the default, the CLI installs @tailwindcss/turbopack instead of @tailwindcss/postcss, skips postcss.config.mjs and writes a loader rule into next.config.ts:

ts
// next.config.ts: the rule create-next-app 16.4.5 adds (its other default options left out)
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
turbopack: {
rules: {
"*.css": {
loaders: ["@tailwindcss/turbopack"],
as: "*.css",
},
},
},
};
export default nextConfig;

That rule is Turbopack configuration, so a webpack build (next dev --webpack) never reads it. If you need webpack for a plugin, use the PostCSS route below instead. Version 16.3.6 and earlier still wrote postcss.config.mjs, which is why tutorials from this summer show a different file than your new app has.

Existing app: install Tailwind v4 with PostCSS

This is the route the Next.js CSS docs and Tailwind's Next.js guide both document, and it works under Turbopack and webpack.

bash
npm install -D tailwindcss @tailwindcss/postcss
js
// postcss.config.mjs
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;
css
/* app/globals.css */
@import "tailwindcss";
tsx
// app/layout.tsx
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

Run npm run dev, put className="text-3xl font-bold" on a heading, and it should render bold and large. That is all an install of Tailwind v4 in Next.js 16 needs. Use one integration, not both: either postcss.config.mjs or the Turbopack loader rule.

Where does the Tailwind v4 config go in Next.js?

In app/globals.css, right after the import. The Tailwind v4 config is CSS: every variable in an @theme block becomes both a CSS variable and a set of utilities.

css
@import "tailwindcss";
@theme {
--color-brand: #d63f00;
--radius-card: 1.25rem;
--breakpoint-3xl: 120rem;
}

That gives you bg-brand, text-brand, rounded-card and a 3xl: breakpoint. The variable's namespace decides which utilities it feeds: --color-* for colors, --font-* for font families, --radius-*, --shadow-*, --breakpoint-* and so on.

Values that change between light and dark belong in plain CSS variables, mapped with @theme inline:

css
:root {
--surface: #ffffff;
--surface-foreground: #1f1f1f;
}
.dark {
--surface: #1b1b1f;
--surface-foreground: #ededed;
}
@theme inline {
--color-surface: var(--surface);
--color-surface-foreground: var(--surface-foreground);
}

With inline, Tailwind writes the reference into the utility, so bg-surface compiles to background-color: var(--surface) and follows the nearest .dark. Without inline, the utility points at --color-surface, which resolves where it is declared, on :root. That still works while .dark sits on <html>, as next-themes puts it, but a .dark section deeper in the page keeps the light value. The pillar post on Tailwind v4 design tokens goes through a complete token set: surfaces, text levels, tones, elevation and a contrast check.

How do I use next/font with Tailwind v4?

next/font exposes each font as a CSS variable, and @theme inline turns that variable into font-sans or font-mono. The layout sets the variables on <html>:

tsx
// app/layout.tsx
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({ variable: "--font-geist-sans", subsets: ["latin"] });
const geistMono = Geist_Mono({ variable: "--font-geist-mono", subsets: ["latin"] });
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<body>{children}</body>
</html>
);
}
css
@theme inline {
--font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
--font-mono: var(--font-geist-mono), ui-monospace, monospace;
}

Use inline here, as the Next.js font docs do. A plain @theme reference resolves on :root, which only works while the font classes sit on <html>. Move them to <body> and font-sans silently falls back to the system font; with inline it works on either element.

Tailwind's base styles set the html font to --font-sans, so the whole page picks up Geist with no class. There is one catch in the 16.4.5 starter: its globals.css ends with body { font-family: Arial, Helvetica, sans-serif; }. The demo page hides that by putting font-sans on its wrapper div. Replace page.tsx with your own markup and everything renders in Arial. Delete that line. Adding font-sans to <body> does not help, for the reason in error 3 below.

Why is Tailwind v4 not working in Next.js?

Usually one of five setup errors, each with a message or a symptom you can match.

1. "It looks like you're trying to use tailwindcss directly as a PostCSS plugin"

Your postcss.config.mjs still says tailwindcss: {}. In v4 the PostCSS plugin moved to its own package. Install @tailwindcss/postcss, replace the key, and remove autoprefixer while you are there.

2. tailwind.config.js changes do nothing

v4 does not look for a config file. Move theme.extend into @theme, darkMode into @custom-variant (error 4) and plugins into @plugin "plugin-name"; lines. For a gradual move you can load the old file with @config "../tailwind.config.js"; under the import. The same change explains why npx tailwindcss init fails: the tailwindcss package no longer ships a command line tool. Migrating a shadcn project? The shadcn Tailwind v4 migration guide covers the codemod and what it misses.

3. Some classes are missing or lose to other CSS

Open DevTools on the element. If the class has no rule at all, Tailwind never saw it:

  • Files outside the project root. In a monorepo, components in packages/ui are not scanned from apps/web. Add @source "../../../packages/ui/src"; to apps/web/app/globals.css (the path is relative to the CSS file).
  • Class names built at runtime. `bg-${tone}-500` never appears as text, so it is never generated. Write the full names in a map, { danger: "bg-red-500", success: "bg-green-500" }.
  • @apply in a CSS module. A .module.css file is compiled on its own and fails with "Cannot apply unknown utility class". Put @reference "../globals.css"; (the path from the module to your stylesheet) at the top of the module.

If the rule exists but is crossed out, cascade layers are the cause. v4 puts utilities in @layer utilities, and any rule outside a layer beats every layered rule, whatever its specificity. That is why the starter's unlayered body { font-family: Arial } wins over font-sans on the same element. Wrap your own global rules in @layer base { ... } and utilities win again.

4. dark: classes ignore the theme toggle

By default dark: compiles to @media (prefers-color-scheme: dark), so it follows the operating system and ignores the class that next-themes sets. Add one line:

css
@custom-variant dark (&:where(.dark, .dark *));

Then pass attribute="class" to the next-themes ThemeProvider and delete the starter's @media (prefers-color-scheme: dark) block, or the system setting keeps overriding your toggle. The Tailwind v4 dark mode guide covers tokens and the toggle, and the next-themes hydration error post covers the flash on reload.

5. New classes appear only after a restart

You add a class, save, and nothing changes until you restart next dev. A Tailwind discussion from May 4, 2026 (opens in a new tab) reports exactly this on Next.js 16. Since Next.js 16.1, Turbopack also keeps its dev cache on disk in .next/dev/cache/turbopack and reuses it on restart, so a stale result can survive one. The order that works for us:

  1. Stop the dev server and delete the cache: rm -rf .next.
  2. Check that only one integration runs (no PostCSS config next to a Turbopack loader rule).
  3. To isolate the bundler, run next dev --webpack with the PostCSS setup. If the problem disappears, it is a Turbopack issue worth reporting with a reproduction.

How do I add components on top of this setup?

A component library built for Tailwind v4 only needs the tokens it uses to exist in your @theme. Wingo UI's init command merges them into app/globals.css and adds the cn helper:

bash
npx wingo-ui@latest init
npx wingo-ui@latest add button card ui-config

The Button, Card and UIProvider are free items. They use the semantic tokens from the sections above (bg-surface, shadow-raised, text-muted-foreground), so they switch with your .dark class without a single dark: prefix. A server page can render them directly:

tsx
// app/page.tsx
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
export default function Page() {
return (
<main className="mx-auto max-w-md p-6">
<Card
title="Tailwind v4 is running"
description="Tokens from globals.css, fonts from next/font, components from Wingo UI."
footer={<Button tone="brand">Continue</Button>}
/>
</main>
);
}
Hover or press the card: it lifts onto a deeper shadow and dips while pressed, and its fill and text come from the surface tokens in both themes
$ npx wingo-ui@latest add card
FreeCard docs

Shared defaults go in the root layout, so every button in the app gets the same shape without repeating props. UIProvider is a client component; a server layout can render it and pass plain objects:

tsx
// app/layout.tsx (inside <body>)
import { UIProvider } from "@/lib/ui-config";
<UIProvider defaults={{ button: { radius: "full", size: "lg" } }}>{children}</UIProvider>
Click the button: it dips while pressed, then shows its loading state at the same width, and every color it uses comes from the tokens in globals.css
$ npx wingo-ui@latest add button
FreeButton docs

The Next.js component library setup guide walks through init, "use client" boundaries and updates in detail, and the theming docs list every token. More posts on this stack live under Next.js and Tailwind CSS.

What do the final files look like?

For an existing app on the PostCSS route, three files hold the entire setup:

js
// postcss.config.mjs
const config = { plugins: { "@tailwindcss/postcss": {} } };
export default config;
css
/* app/globals.css */
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
:root {
--background: #ffffff;
--foreground: #1f1f1f;
--surface: #ffffff;
}
.dark {
--background: #111113;
--foreground: #ededed;
--surface: #1b1b1f;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-surface: var(--surface);
--font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
--font-mono: var(--font-geist-mono), ui-monospace, monospace;
}
@layer base {
body {
background: var(--background);
color: var(--foreground);
}
}

The layout is the next/font version above. On the create-next-app route, swap postcss.config.mjs for the turbopack.rules entry in next.config.ts; globals.css and the layout stay the same.

Next step

If the setup works and you want components that already speak these tokens, npx wingo-ui@latest add button card installs both free components from this post, with UIProvider as a dependency, and needs no account. All 75 free items install the same way, and the installation docs cover Vite and existing projects.

Components in this post

  • Button

    The React button component every screen starts with: five variants, six tones, all sizes, and a loading state that never jumps.

    Free
  • Card

    A React card component for listings, stats, settings and plans: media, header, body and footer parts, and a lift-and-press mode.

    Free
  • UIProvider

    A React config provider for Wingo UI: app-wide default props for every component, the Intl locale and a reduced-motion policy.

    Free

FAQ

Does Tailwind v4 need a tailwind.config.js in Next.js?

No. Tailwind v4 reads its configuration from CSS: theme values go in @theme blocks in app/globals.css and source files are detected without a content array. A v3 config file is ignored unless you load it with @config "../tailwind.config.js"; in the stylesheet.

Should I use @tailwindcss/postcss or @tailwindcss/turbopack?

Both compile the same CSS under Turbopack, the default bundler in Next.js 16. create-next-app 16.4 and later writes the Turbopack loader; the Tailwind and Next.js docs still show the PostCSS plugin, which also works when you run next dev --webpack. Pick one, not both.

Why are my Tailwind classes not applied in Next.js?

Check four things in order: the class exists in the built CSS (DevTools), the file is inside the detected sources (add @source for monorepo packages), the class name is written out in full (no bg-${color}-500), and no unlayered rule in another stylesheet overrides it.

Do I still need autoprefixer with Tailwind v4?

No. Tailwind v4 adds vendor prefixes and handles @import itself, so the PostCSS config needs only @tailwindcss/postcss. Remove autoprefixer and postcss-import from older configs.

Which browsers does Tailwind v4 support?

Tailwind's compatibility page lists Chrome 111, Safari 16.4 and Firefox 128 as the minimum, because v4 relies on cascade layers, @property and color-mix(). If you must support older browsers, stay on Tailwind v3.4.

Try it in your project

Button

Free

The React button component every screen starts with: five variants, six tones, all sizes, and a loading state that never jumps.

75 components free, no account needed. Pro from $8 a month.

Open Button liveSee pricing
  • Tailwind CSS v4
  • Next.js 16
  • Setup
  • Turbopack
  • next/font

Share

SR

About the author

Serban Rusu

Founder of Wingo UI

Serban Rusu founded Wingo UI. He builds its component library, CLI and MCP server, and writes about React interfaces for phones and AI coding agents.

More from Serban
Keep reading

Related posts

All posts
Next.js and Tailwind CSS

shadcn Tailwind v4 Migration: Step by Step From v3

A shadcn tailwind v4 migration in order: the upgrade codemod, tailwind.config into @theme inline, hsl to oklch, border and ring fixes, and tw-animate-css.

SRSerban Rusu·Nov 6, 2026·10 min read
Next.js and Tailwind CSS

shadcn Vite Setup with Tailwind CSS v4 and React 19

shadcn Vite setup tested on Vite 8 and TypeScript 6: the Tailwind v4 plugin, the @ alias in tsconfig.app.json, dark mode without Next.js, then add components.

SRSerban Rusu·Oct 13, 2026·7 min read
Next.js and Tailwind CSS

Tailwind v4 Design Tokens: Colors, Dark Mode and Contrast

Tailwind v4 design tokens from a production React library: @theme inline, semantic surfaces, status colors, dark mode and a contrast check you can run in CI.

SRSerban Rusu·Oct 9, 2026·20 min read
Newsletter

Get new posts by email

New posts, product news and occasional offers from Wingo UI. We count clicks to keep it relevant.

No spam. Unsubscribe at any time.

WingoUI

Animated, configurable, mobile-first React components and blocks. Copy the source, make it yours, and let your coding agent build with it.

Product

  • Components
  • Templates
  • Pricing
  • AI agents
  • For teams
  • Theme generator

Resources

  • Docs
  • Contact
  • Programs
  • Blog
  • Changelog
  • Changelog RSS
  • llms.txt

Compare

  • Wingo UI vs paid kits
  • Wingo UI vs shadcn/ui
  • shadcn/ui alternatives
  • MUI alternatives
  • Tailwind Plus alternatives
  • Magic UI alternatives
  • Free components

Legal

  • Terms
  • Privacy
  • Refunds
  • License
  • Imprint

Component categories

  • Buttons & Actions
  • Inputs
  • Forms
  • Navigation
  • Overlays
  • Feedback
  • Data Display
  • Tables & Lists
  • Charts & Stats
  • Layout
  • Media
  • AI Kit
  • Text & Effects
  • Mobile
  • Commerce
  • Marketing Sections
  • Blocks
  • Hooks & Utilities

© 2026 Wingo UI

Wingo UI