When Tailwind CSS v4 dropped, I'll admit I was skeptical. Tailwind v3 worked fine. The utility-first approach had already won me over years ago, and I didn't see what needed fixing. Then I migrated this portfolio site from v3 to v4, and within a day, I understood. This isn't a minor version bump — it's a complete engine rewrite, and the improvements are substantial.
No More tailwind.config.js
The most jarring change: the JavaScript config file is gone. All configuration now lives in your CSS file using the @theme directive. At first this felt like a downgrade — I loved the autocomplete I got from the JS config. But in practice, having your design tokens defined right next to your CSS makes more sense. The new approach also means Tailwind can parse your config without spinning up a JavaScript runtime, which is a big part of why the new engine is so much faster.
/* globals.css — Tailwind v4 configuration */
@import 'tailwindcss';
@theme inline {
--color-primary: #FFC700;
--color-background: #000000;
--color-foreground: #ffffff;
--color-muted-foreground: #a1a1a1;
--color-border: #424242;
--font-sentient: 'Sentient', serif;
--font-mono: 'Geist Mono', monospace;
}The Speed Difference Is Real
Tailwind v4's new Oxide engine is written in Rust, and the performance gains aren't marketing fluff. On this portfolio project with 15+ page routes and 30+ components, the initial CSS build went from ~800ms to ~8ms. That's a 100x improvement. Hot reloads that add new utility classes are imperceptible. In a large monorepo I work on at my day job, the CSS build step went from being one of the slowest parts of the pipeline to being essentially free.
Native CSS Features Over JavaScript
V4 leans heavily into modern CSS features that browsers now support natively. Container queries, cascade layers, color-mix(), and native nesting are all first-class citizens. Instead of generating JavaScript-based workarounds, Tailwind now emits the native CSS equivalents. The output is smaller, faster to parse, and easier to debug in browser DevTools.
Migration Pain Points
Let me be honest — the migration wasn't painless. A few things that tripped me up:
- The @apply directive works differently with the new engine. Some complex @apply chains needed to be refactored.
- Plugin syntax changed significantly. If you relied on third-party Tailwind plugins, check compatibility first.
- The opacity modifier syntax changed from bg-primary/[0.1] in some edge cases. Most worked fine, but a few needed adjustment.
- Dark mode configuration moved from the JS config to a CSS-based approach using @variant.
Is It Worth Upgrading?
Absolutely yes, but time it wisely. If you're starting a new project, use v4 without question. If you're maintaining an existing v3 project, I'd recommend migrating during a planned refactor rather than as a standalone effort. The Tailwind team provides an upgrade tool that handles most of the mechanical changes, but you'll still need to manually adjust some patterns. Budget a day for a medium-sized project. The long-term DX improvement is worth the upfront investment.