Tailwind CSS 4: new engine and configuration
A calm assessment of the Oxide engine and CSS-first configuration approach that Tailwind CSS 4 brings — with the composure a major version bump deserves.
Tailwind CSS 4 shipped as a stable release in January 2025. When I adopted the utility-first approach five years ago, I got a fair amount of pushback from the people around me; those same people are using Tailwind now. Major version bumps always break something and always gain something. I want to take a calm look at what broke and what was gained.
The most visible change from Tailwind 3 to 4 is that tailwind.config.js is no longer required. I have written that file, read it, and overwritten it in other people’s projects for years. I’m not sad to see it go.
Oxide engine: what changed
Under the hood, Tailwind 4 runs on a new build engine called Oxide. Written in Rust, it claims up to ten times faster full build times and up to a hundred times faster incremental builds compared to the previous JavaScript-based engine.
You actually feel that difference in a development environment. The waiting time you used to spend while building a large project with Tailwind 3 is almost gone with version 4. Production builds benefit too, though there the time was already just a few seconds — the real difference is in the development loop.
CSS-first configuration
The biggest paradigm shift in Tailwind 4 is moving configuration into CSS. Theme customizations and plugins are no longer defined in a JavaScript file; instead, they live directly in CSS via the @theme directive.
@import "tailwindcss";
@theme {
--color-brand: oklch(55% 0.2 250);
--font-display: "Inter", sans-serif;
--spacing-18: 4.5rem;
}
This approach has a few consequences. First, configuration now works as CSS custom properties, which means it’s accessible both in the browser and in JavaScript. Second, dropping tailwind.config.js simplifies the toolchain a little. Third, it creates a migration cost for existing projects.
Migration cost
The most important things to watch when migrating from v3 to v4:
- The
@tailwind base/components/utilitiesdirectives are gone, replaced by@import "tailwindcss". - The
theme()andscreen()functions have been replaced with CSS variables. - Many JIT (Just-In-Time) defaults changed, especially
ring,shadow, and border color defaults. - Custom plugins can now be written as CSS or JavaScript instead of the
plugin()API, though the API still exists.
The @tailwindcss/upgrade CLI tool provided by the Tailwind team automates most of this migration. I ran it on a small project; the majority of changes were applied automatically, and the remaining manual steps were documented.
npx @tailwindcss/upgrade
On a large project you’ll want to review the tool’s output before trusting it fully. Automated migrations are generally correct, but project-specific customizations can sometimes slip through the cracks.
Vite plugin and CSS-first import
Tailwind 4 now offers a first-class Vite plugin alongside the PostCSS plugin. For Vite-based projects, using this plugin instead of a PostCSS configuration is cleaner:
// vite.config.js
import tailwindcss from "@tailwindcss/vite";
export default {
plugins: [tailwindcss()],
};
With this configuration, a single @import "tailwindcss" line in your CSS file is all you need — no separate PostCSS config required.
New utility classes
A few of the new utility classes in v4 stand out. field-sizing-content makes it possible to auto-size <textarea> elements to their content with a single class. The color-scheme utilities give more direct control over dark mode transitions. inset-shadow-* expands inset shadow support.
Assessment
Tailwind 4 is not the kind of release to approach with the fear that “it works, but all my accumulated knowledge is now worthless.” The core utility-first philosophy hasn’t changed. The Oxide engine delivers a real speed gain. CSS-first configuration means configuration lives in a more natural place long term — inside CSS itself.
I’m not rushing to migrate existing projects. For new projects, starting with v4 is now the natural choice. As with every major version jump: the tool’s change shifts the ecosystem, but the underlying logic of the building blocks stays the same. You understand that by using it, not by reading about it.
Comments
Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.