Key Takeaway
Tailwind CSS v4, released January 2025, is a ground-up rewrite built on the Rust-based Oxide engine. Configuration moves from tailwind.config.js into CSS through the theme directive, content detection becomes automatic, and design tokens ship as native CSS variables. Full builds run up to five times faster and incremental rebuilds are measured in microseconds.
I have shipped this portfolio on Tailwind v3.4 for a long time, and it still works fine. But Tailwind CSS v4, released on 22 January 2025, is not a routine minor bump — it is a full rewrite of the framework's internals. Understanding what changed matters even if you are not upgrading today, because the mental model for how Tailwind is configured is now fundamentally different.
The headline is a new engine the team calls Oxide, written largely in Rust, paired with a shift the docs describe as CSS-first configuration. Instead of a JavaScript config file, your design system now lives in your stylesheet. This post walks through the pieces that matter in practice: the config change, automatic content detection, the migration path, and the real build-speed numbers.
CSS-first configuration replaces the config file
In v3 you tuned your theme in tailwind.config.js — a JavaScript object for colors, spacing, fonts, and breakpoints. In v4 that moves into CSS. You import Tailwind with a single line and declare your tokens inside a theme block, using plain custom-property syntax. Every value you define is emitted as a real CSS variable, so your tokens are available to any stylesheet or inline style without a build step to read them.
@import "tailwindcss";
@theme {
--font-display: "Satoshi", sans-serif;
--color-brand-500: oklch(0.84 0.18 117.33);
--spacing-gutter: 2rem;
--ease-fluid: cubic-bezier(0.3, 0, 0, 1);
}This is more than cosmetic. Because the theme is CSS, colors use the modern oklch color space for a wider P3 gamut, and values like fonts and easing curves are addressable as variables anywhere in your app. A JavaScript config is still possible for edge cases through an explicit config directive, but it is no longer auto-detected — the CSS file is the source of truth.
Automatic content detection and native CSS variables
v3 required a content array listing every glob where class names might appear; forget a path and those utilities silently vanished from the build. v4 detects your template files automatically. It heuristically scans your project, ignoring anything in your .gitignore and skipping binary files, so new folders just work. When you need to pull in a source outside the defaults, such as a component library in node_modules, you add it explicitly with a source directive.
Automatic detection does not mean you lose control. The source directive lets you add paths the heuristic skips, and you can point it at packages under node_modules to scan a design-system library you consume. Treat it as an escape hatch, not the default — for most apps you write no content configuration at all.
Migrating from v3: one import, one command
The most visible change on day one is the entry stylesheet. The three at-tailwind directives that seeded base, components, and utilities collapse into a single import of tailwindcss. The PostCSS plugin also moved into its own package, and both postcss-import and autoprefixer are handled for you now, so you can drop them from your pipeline.
/* v3: three directives in your entry CSS */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* v4: one import, theme lives in CSS */
@import "tailwindcss";# Automated migration (requires Node.js 20+)
npx @tailwindcss/upgrade
# The PostCSS plugin now ships as its own package
npm i tailwindcss @tailwindcss/postcssYou do not have to do this by hand. The team ships an automated upgrade tool that updates dependencies, migrates the config file into CSS, and rewrites renamed utilities across your templates. It needs Node.js 20 or newer, and the docs recommend running it on a fresh branch so you can review the diff. Expect renamed classes too — shadow-sm became shadow-xs, and the important modifier moved to the end of the class.
The Oxide engine and the speed numbers
Oxide is why all of this is fast. Tailwind Labs rewrote the hot paths in Rust and leaned on native CSS features like cascade layers and registered custom properties instead of emulating them in JavaScript. The published benchmarks against v3.4 are concrete rather than vague:
- Full builds run about 3.78 times faster — roughly 378ms down to 100ms in the reference benchmark.
- Incremental rebuilds that add new CSS are about 8.8 times faster, dropping from 44ms to 5ms.
- Incremental rebuilds with no new CSS are over 100 times faster and land in microseconds — around 192 microseconds in the published figures.
v4 targets modern browsers only: Safari 16.4 and up, Chrome 111 and up, and Firefox 128 and up. It depends on features like the property at-rule and color-mix that have no polyfill. If you must support older browsers, stay on v3.4 — this is the single biggest reason not to upgrade blindly.
Tailwind v3.4 vs v4.0 at a glance
| Concern | Tailwind v3.4 | Tailwind v4.0 |
|---|---|---|
| Configuration | JavaScript tailwind.config.js | CSS theme directive |
| Entry stylesheet | Three at-tailwind directives | One import of tailwindcss |
| Engine | JavaScript and PostCSS | Oxide, written in Rust |
| Content detection | Manual content globs | Automatic, with source overrides |
| Full build speed | Baseline | About 3.8x faster |
| Browser target | Broad, older browsers | Safari 16.4+, Chrome 111+, Firefox 128+ |
For this portfolio, still on v3.4, the calculus is simple: the browser floor is fine for my audience, and the upgrade tool does most of the work, so v4 is a when-not-if. The real win is not raw speed I will rarely notice on a small site — it is that the design system finally lives in CSS, where it belongs. That is the change worth planning for.

