Tailwind v4: the changes that matter
CSS-first config, @theme, generated utilities — here's what Tailwind v4 changes in our workflow.
Tailwind v4 isn't an update, it's a shift in nature. v3 was a JavaScript tool that wrote CSS. v4 is CSS that uses the browser's capabilities. You see it from the first file.
This site runs on Tailwind 4.3. Here's what actually changed in our daily work.
The configuration file is gone
In v3, your palette, fonts and breakpoints lived in tailwind.config.js — a JavaScript file, invisible from a stylesheet, that you had to read through to understand where a colour came from.
In v4, that file no longer exists. Ours was replaced by a @theme block in the CSS:
@import 'tailwindcss';
@theme {
--color-ink: #0e0e0c;
--color-bone: #f2ebdb;
--color-acid: #ccff33;
--color-rust: #e94e1b;
--font-display: 'Fraunces', 'Times New Roman', serif;
--font-sans: 'Geist', system-ui, sans-serif;
}
Three immediate consequences:
- A single import line replaces the three old
@tailwind base,@tailwind componentsand@tailwind utilitiesdirectives. - Each value becomes a native CSS variable.
--color-acidis usable in a Tailwind class (bg-acid) and in hand-written CSS (var(--color-acid)). In v3, these two worlds didn't talk to each other without a plugin. - Your tokens are readable at runtime. A component can read a colour from the theme from JavaScript, which was impossible when it was compiled into a configuration file.
We use it to compose derived colours directly in the theme:
--color-ink-soft: color-mix(in srgb, var(--color-ink) 68%, var(--color-bone));
This line wouldn't have made sense in v3.
PostCSS is no longer in the middle
Our project contains neither tailwind.config.js nor postcss.config.js. The official Vite plugin (@tailwindcss/vite) is enough. The new engine is written in Rust, and building our 219 pages, stylesheets included, takes just over six seconds.
Fewer configuration files means fewer places where behaviour can hide. On a project picked up two years later, that's what costs the most.
The price to pay: the browser
This is the point the announcements gloss over. Tailwind v4 relies on modern CSS features: @property, color-mix(), cascade layers (@layer). In practice, this means Safari 16.4, Chrome 111 and Firefox 128 at minimum.
If your audience includes corporate workstations locked to old versions — common in industry and government — check your analytics before migrating. There's no automatic fallback: on a browser that's too old, the layout doesn't degrade, it breaks.
For a public-facing site in 2026, the question is settled. For an intranet, it deserves five minutes of analysis.
What actually changes in the work
- Arbitrary values recede. When a token is a CSS variable,
bg-[#ccff33]becomes pointless: you writebg-acid, and the colour stays editable in one place. - The boundary between Tailwind and hand-written CSS fades. Our Astro components mix utility classes and scoped
<style>blocks that consume the same variables. No more palette duplication. - Migration from v3 is real. The
npx @tailwindcss/upgradetool does most of the work, but third-party plugins and elaborate configurations need manual rework. Budget half a day on a medium-sized project, not ten minutes.
Should you migrate?
New project: yes, without question.
Existing v3 project that works: no rush. v3 keeps working. The right time is a visual redesign, when you were going to touch the palette anyway.
Project with lots of third-party plugins: check their v4 compatibility first. That's where the nasty surprises hide, not in the core of the tool.