← All posts

What Changed When Tailwind Went CSS-First

Topic: Coding

For a few years, every Tailwind project had the same skeleton: install the package, generate a tailwind.config.js, and extend a theme object with whatever colors and fonts your design called for. Version 4 removes that file entirely from the default workflow and moves configuration into CSS itself, via an @theme block.

The practical effect is that a color token like --color-accent: #2B5F63 defined inside @theme is simultaneously a CSS custom property you can reference anywhere (var(--color-accent)) and a Tailwind utility generator — it produces bg-accent, text-accent, border-accent, and so on, automatically. There’s no separate JS object to keep in sync with your CSS; the token is defined once, in the same file where the rest of your styling lives.

The other adjacent change is how the framework attaches to a build tool. Rather than a PostCSS plugin wired up through framework-specific integrations (like the old @astrojs/tailwind package), v4 ships a dedicated Vite plugin, @tailwindcss/vite, that most modern meta-frameworks — Astro included — can drop straight into their Vite config. Plugins like Typography follow the same CSS-first pattern: rather than an entry in a plugins: [] array in a JS config, you add @plugin "@tailwindcss/typography"; directly in your CSS.

None of this changes what Tailwind actually does day to day, but it does mean older tutorials that reference tailwind.config.js are describing a different setup than what a fresh install gives you now — worth knowing before spending time debugging a config file that no longer exists by default.


Daniel Kuhman
Daniel Kuhman

Delusional optimist. Biomechanics and Motor Control researcher. Data science and analytics by day, hacker by night; created Crowd Card and Refology. Contributing developer to Silk Pyjamas and The Work App.