Migrating to Tailwind CSS v4: Everything That Changed
Tailwind CSS v4 brought the biggest changes since the framework's inception. The shift from JavaScript configuration to CSS-native configuration is a fundamental rethinking of how utility-first CSS works.
The Big Changes
1. CSS-Based Configuration
Gone is tailwind.config.ts. Everything is now configured in CSS:
@import "tailwindcss";
@theme inline {
--color-primary: #0ea5e9;
--color-background: #0f172a;
--font-heading: "Space Grotesk", sans-serif;
}
2. Lightning CSS Engine
Tailwind v4 uses Lightning CSS (written in Rust) instead of PostCSS for processing. Build times dropped by 5-10x in our projects.
3. Custom Variants
The new @custom-variant syntax replaces plugin-based variants:
@custom-variant dark (&:is(.dark *));
4. Automatic Content Detection
No more content configuration — Tailwind v4 automatically detects which files to scan.
Migration Steps
- Remove
tailwind.config.ts— Move all configuration to your CSS file - Update
@applyusage — Some complex@applychains need adjustment - Replace
theme()calls — Use CSS variables instead:var(--color-primary) - Update plugins — Many plugins need v4-compatible versions
- Test dark mode — The class strategy syntax changed
Common Gotchas
@applyin component libraries — Some shadcn/ui components need updates- Custom color syntax —
bg-primary/50opacity syntax still works, but custom colors use the CSS variable format - JIT behavior — All classes are now JIT by default, some edge cases behave differently
Performance Results
After migrating three production projects:
- CSS bundle size: -15% average
- Build time: -60% average
- Dev server startup: -70%
The migration was worth it for every project.
Originally published on IceCat Studio Blog. Based on our migration experience with multiple production projects.