Tailwind CSS v4 Guide: New Engine and CSS-first Configuration

Tailwind CSS v4 is a ground-up rewrite of the framework: official benchmarks show full builds over 3.5x faster, incremental builds over 8x faster, and incremental builds that generate no new CSS up to ~100x faster — measured in microseconds. For website teams, that means near-instant style feedback even on large projects: save the file, refresh the page, and the change appears almost immediately, making development feel "buildless."

v4 isn't a patch release. It moves the mental burden of configuration from JavaScript to CSS: no more tailwind.config.js, no content array to maintain — theme variables, breakpoints, and custom colors all live in CSS itself. Below we walk through the new engine, installation, configuration, and upgrading from v3.

For Tailwind page examples, see the Tailwind page template on 16IDC; Tailwind is also a mainstream styling option under the frontend building category.

New Engine and Modern CSS

v4 leans on modern CSS: native cascade layers (@layer) give finer control over rule precedence, @property registers custom properties (making gradients animatable), color-mix() lets any color — including CSS variables and currentColor — adjust opacity, and logical properties simplify RTL support while shrinking generated CSS. The default palette also moved from rgb to oklch, producing more vivid colors.

These features deliver tangible benefits. Take gradients: in v3, bg-gradient-to-r only did linear gradients; v4 provides bg-linear-to-r, bg-radial, and bg-conic for linear, radial, and conic respectively. Combined with color-mix(), you can even adjust the opacity of currentColor directly — color scenarios that previously needed hand-written custom CSS now fit in a single utility class.

Simplified Installation

v4 condenses setup to three steps: install tailwindcss and @tailwindcss/postcss, add the PostCSS plugin, then write one line of CSS — @import "tailwindcss". No more @tailwind directives, no tailwind.config.js, and no content array: template files are discovered automatically through heuristics (auto-ignoring .gitignored files and binaries), with the @source directive available when you need to add sources explicitly.

For the common Vite case:

npm install tailwindcss @tailwindcss/vite

Register the plugin in vite.config.js and drop @import "tailwindcss" into your entry CSS — that's the whole setup. Compared with v3's tailwind.config.js + postcss.config.js + the @tailwind base/components/utilities trio, the configuration overhead drops by more than half.

CSS-first Configuration and Theme Variables

Configuration moves from JavaScript to CSS: define design tokens in @theme to extend spacing, colors, breakpoints, and fonts.

@import "tailwindcss";

@theme {
  --color-avocado-500: oklch(0.84 0.18 117.33);
  --breakpoint-3xl: 1920px;
  --font-display: "Satoshi", "sans-serif";
}

All design tokens are emitted as CSS variables by default, usable at runtime and passable to animation libraries. This means the "design system" and the code genuinely share one set of variables: a designer hands you a color, you put it in @theme, and every button, border, and gradient across the project follows.

Dynamic Utilities and Variants

Spacing utilities (px-*, mt-*, w-*) are now derived from a single --spacing variable and accept any value out of the box — e.g. w-17, grid-cols-15. New capabilities include container queries (@container/@sm:), the not-* variant, starting (for enter transitions via @starting-style), 3D transforms (rotate-x-*, perspective-*), and richer gradient APIs (bg-linear-*, conic/radial). Utilities like color-scheme, field-sizing, and inset-shadow-* are also built in.

Container queries deserve special attention: they let a component respond to the width of its own container rather than the viewport, which is far more natural for reusable components like cards and sidebars. One @container plus one @md:flex-col makes the same component stack automatically in a narrow container.

Tooling Integration

Vite users can adopt the official @tailwindcss/vite plugin for even better performance with less configuration (see the Vite build tool guide). v4 also bundles @import support, so no postcss-import is needed to merge multiple CSS files. Webpack, Rollup, Svelte, Remix, and Nuxt all have official or community integration paths; the migration is usually "swap the old plugin, change one import line."

Upgrading from v3

Tailwind ships an automated upgrade tool plus a guide: run npx @tailwindcss/upgrade to handle most changes, then manually review renamed classes (e.g. bg-gradient-*bg-linear-*), removed config options, and shadow/border default changes.

The three most common upgrade pitfalls: (1) old utilities that were renamed or removed (e.g. pre-shrink-0 versions of flex-shrink-0); (2) custom theme still living in tailwind.config.js instead of @theme, causing utilities to silently disappear; (3) changed @import order altering the cascade results of existing CSS. After upgrading, run a visual regression pass and check buttons, shadows, and borders closely. For responsive page structure, see the responsive navbar template and the HTML page template.

Key differences: v3 vs v4

Item v3 v4
Configuration tailwind.config.js @theme in CSS
Content scanning Manual content array Auto-detection + @source
Gradient classes bg-gradient-* bg-linear-* etc.
Spacing units Fixed steps Derived from --spacing
Full build Baseline 3.5x+ faster

FAQ

Styles broke after upgrading? First check for leftover tailwind.config.js settings that weren't migrated to @theme, and for a mix of v3 and v4 plugins.

A utility isn't applying? Confirm the file is covered by automatic content detection; if it lives in node_modules or is gitignored, declare it explicitly with @source.

Source: https://tailwindcss.com/blog/tailwindcss-v4; upgrade guide: https://tailwindcss.com/docs/upgrade-guide