
September 08, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
Tailwind CSS 4 What Changed and How to Migrate is the question every team asks after a major release reshapes the build pipeline. Version 4 replaces the PostCSS-only workflow with an Oxide engine, moves configuration into CSS, and drops the old @tailwind directives. If you ship production web applications in Nepal or abroad, the upgrade affects every Blade template, Vite config, and CI build step you maintain.
@import "tailwindcss", and CSS-first @theme config. Run npx @tailwindcss/upgrade, swap the Vite plugin, update content paths with @source, then fix breaking utility defaults.What are the biggest changes in Tailwind CSS 4?
Tailwind CSS 4 is a ground-up rewrite, not a patch release. The team rebuilt the compiler in Rust under the Oxide project. Builds on large codebases often finish in milliseconds instead of seconds. That speed matters when your GitLab CI pipeline runs lint, test, and asset build on every push.
The configuration model flipped entirely. Tailwind CSS 3 expected a JavaScript tailwind.config.js file. Version 4 prefers CSS-native directives. You define design tokens inside @theme blocks in your main stylesheet. The old config file still works through a compatibility layer, but new projects should start CSS-first.
Import syntax changed too. The three @tailwind base, @tailwind components, and @tailwind utilities directives are gone. One line replaces them:
@import "tailwindcss"; Content detection is smarter but less magical than it sounds. Tailwind scans files automatically when you use the Vite plugin. For Laravel Blade views, pagination templates, and compiled views in storage/framework/views, you still declare paths explicitly with @source. I have missed compiled Blade paths on client projects and wondered why pagination styles vanished after deploy.
Native CSS features got first-class support. Custom properties defined in @theme become real CSS variables at runtime. You can reference them in plain CSS or inline styles without a build step. Container queries, @starting-style, and modern color formats like OKLCH work out of the box.
The npm package structure split. Core lives in tailwindcss. Bundler integration ships as @tailwindcss/vite or @tailwindcss/postcss. The official upgrade CLI is @tailwindcss/upgrade. Keep these names straight when reading older tutorials that still reference a single PostCSS plugin chain.
Version 3 vs version 4 at a glance
| Area | Tailwind CSS 3 | Tailwind CSS 4 |
|---|---|---|
| Entry directive | @tailwind base/components/utilities | @import "tailwindcss" |
| Configuration | tailwind.config.js | @theme in CSS (JS optional) |
| Compiler | JavaScript (PostCSS) | Oxide (Rust) |
| Content paths | content: [] in config | @source directives in CSS |
| Vite setup | PostCSS plugin only | Dedicated @tailwindcss/vite plugin |
| Default ring width | 3px | 1px |
| Default border color | gray-200 | currentColor |
For a broader picture of framework upgrades in 2026, see the Laravel 12 features and changes guide. Laravel and Tailwind often upgrade together on the same sprint.
How do you upgrade a Tailwind CSS 3 project to version 4?
Start with a clean git branch and a passing test suite. Tailwind CSS 4 What Changed and How to Migrate is safest when you can diff visual regressions quickly. Storybook helps. So does a staging environment that mirrors production assets.
Run the official upgrade tool first. It rewrites config files, updates imports, and flags deprecated utilities:
npx @tailwindcss/upgrade The CLI targets Node.js 20 or newer. Your CI runners must match. On projects I maintain with Alpine.js in Blade templates, the upgrade tool preserves most class names unchanged. Custom plugins need manual review.
Install the new packages and remove obsolete ones:
npm uninstall tailwindcss postcss autoprefixer
npm install tailwindcss @tailwindcss/vite Update your Vite config. With Vite 8.x on a Laravel 13 project, the plugin replaces the PostCSS chain entirely:
import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
tailwindcss(),
],
}) Replace your CSS entry file contents:
@import "tailwindcss";
@source '..//*.blade.php';
@source '..//*.js';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php'; Delete postcss.config.js unless you rely on other PostCSS plugins. Autoprefixer is built into Tailwind CSS 4. Duplicate prefixing adds bloat without benefit.
- Create a feature branch and snapshot key pages with screenshots.
- Run
npx @tailwindcss/upgradeon a machine with Node.js 20+. - Swap PostCSS for
@tailwindcss/viteinvite.config.js. - Rewrite
app.csswith@import,@theme, and@source. - Build assets with
npm run buildand fix compiler errors. - Walk through forms, modals, navigation, and dark mode manually.
- Deploy to staging before touching production traffic.
If you lack a dedicated front-end developer, a structured website redesign and revamp service can absorb the migration alongside template cleanup. Bundling both tasks avoids paying twice for the same Blade audit.
How does Tailwind CSS 4 configuration work without tailwind.config.js?
The @theme directive is the heart of CSS-first config. You declare design tokens as CSS custom properties. Tailwind generates matching utility classes automatically:
@import "tailwindcss";
@theme {
--color-brand: oklch(55% 0.2 250);
--color-brand-dark: oklch(40% 0.18 250);
--font-display: "Inter", sans-serif;
--breakpoint-3xl: 120rem;
} These tokens produce utilities like bg-brand, text-brand-dark, and font-display. No JavaScript mapping required. The naming convention follows the pattern --{category}-{name}. Colors, spacing, fonts, breakpoints, and shadows all use the same model.
Extend or override defaults by redeclaring the variable. Remove a default token with @theme { --color-teal-*: initial; } syntax to reset an entire color family. That replaces the old corePlugins: false approach from version 3.
Custom utilities belong in CSS too. Use @utility for one-off classes that participate in variant chains:
@utility tab-4 {
tab-size: 4;
} Component classes still work through @layer components, though the Tailwind team encourages utilities over abstractions. On production Laravel apps I prefer small Blade components over large @apply blocks. Components survive upgrades better.
Legacy JavaScript config is supported via @config "../../tailwind.config.js" in your CSS file. Use this as a bridge, not a destination. Migrate tokens into @theme incrementally across sprints.
Mapping old theme.extend values
A config entry like colors: { brand: '#2563eb' } becomes --color-brand: #2563eb inside @theme. Spacing keys map to --spacing-*. Font families map to --font-*. The official Tailwind CSS upgrade guide lists every namespace. Bookmark it during the migration week.
How do you integrate Tailwind CSS 4 with Laravel and Vite 8?
Laravel 13 ships with Vite 8.x by default. PHP 8.3 is the minimum for that stack. Tailwind CSS 4 pairs cleanly with this toolchain. Remove tailwindcss from postcss.config.js and add the Vite plugin instead.
A typical Laravel 13 resources/css/app.css for a project like Adventure Third Pole Trek looks like this:
@import "tailwindcss";
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '..//*.blade.php';
@source '..//*.js';
@theme {
--color-primary: oklch(52% 0.15 160);
--font-sans: "Figtree", ui-sans-serif, system-ui, sans-serif;
} Livewire and Alpine class strings are scanned automatically when their file paths sit inside a declared @source glob. Dynamic class names built from JavaScript variables still fail detection. That limitation existed in version 3 too. Keep a safelist comment or static reference nearby if you rely on runtime-constructed classes.
Commit compiled assets if your production server lacks Node.js. Several sites I deploy through Deployer 7 build front-end assets in GitLab CI and commit the public/build directory. Tailwind CSS 4 produces smaller output files in most benchmarks, which helps page speed optimization scores.
WooCommerce and WordPress projects follow a different path. Those stacks often use Tailwind through theme build tools rather than Vite. See the WordPress development service page if your storefront still runs a classic theme pipeline. Mixing Tailwind CSS 4 into a jQuery-heavy legacy theme without a bundler creates more pain than gain.
For JSON config snippets during the migration, the JSON formatter tool helps validate generated theme exports before you paste them into CSS.
What breaking changes should you watch for during migration?
Breaking changes are manageable but visual. They will not always throw compiler errors. QA every form and focus state after upgrade.
Default border color. Version 3 applied border-gray-200 implicitly. Version 4 uses currentColor. Borders may disappear on elements that never set an explicit color. Add border-gray-200 where needed, or define a default in @layer base.
Ring utilities. Default ring width dropped from 3px to 1px. Focus rings on buttons and inputs look thinner unless you add ring-2 or a custom @theme override. Accessibility audits should include keyboard navigation checks after deploy.
Removed utilities. Deprecated aliases from version 2 finally disappeared. The upgrade tool rewrites most of them. Search your codebase for overflow-ellipsis, old flex shorthand, and opacity modifiers tied to removed color palettes. The regex tester helps batch-search Blade directories for stale class names.
Plugin ecosystem. Community plugins written for the JavaScript API may lag behind Oxide. Typography (@tailwindcss/typography) and forms (@tailwindcss/forms) have version 4 releases. Verify each plugin before upgrading production. A pattern I have seen repeatedly: one unmaintained plugin blocks the entire migration.
Browser support. Tailwind CSS 4 targets Safari 16.4+, Chrome 111+, and Firefox 128+. Older mobile browsers in some markets still matter. Check your analytics before assuming OKLCH and modern @property usage is safe. Provide fallbacks for critical brand colors if your audience skews older.
Dark mode syntax is unchanged for class-based toggling. dark:bg-gray-900 still works. If you used the legacy media strategy in JavaScript config, move it to a CSS variant declaration. Consult the official dark mode documentation for the v4 syntax.
Projects on Bootstrap 5 — common on legal-tech portals like Court Marriage In Nepal — may run Tailwind only on admin panels or new sections. Isolate Tailwind CSS 4 to the Vite-managed assets. Do not load two utility frameworks on the same element without a namespace prefix strategy.
When should you migrate versus stay on Tailwind CSS 3?
Not every project needs immediate migration. Tailwind CSS 3 remains functional. New features land in version 4 first. The decision depends on project age, team capacity, and release cadence.
- Migrate now if you are already upgrading Laravel 12 or 13, Vite 8, or Node.js 26 LTS on CI.
- Migrate now if build times block developer productivity on large monorepos.
- Wait if a critical third-party plugin lacks Oxide support and has no fork.
- Wait if the site enters a freeze period before Dashain or Tihar sales peaks.
- Plan a hybrid bridge if only one module needs new Tailwind features — isolate it in a separate Vite entry.
Greenfield apps should start on version 4 directly. There is no reason to scaffold with deprecated directives in 2026. For e-commerce builds like Quick And Easy Nepalese Grocery, faster rebuilds during checkout UI iteration save real hours across a sprint.
Ongoing support and maintenance contracts should budget one to three days for a medium Laravel app migration. Complex design systems with custom plugins need longer. Document the @theme token file as the single source of truth going forward.
Cross-check your pipeline with the AI code review in CI guide if you want automated class-name linting after the upgrade. Static analysis catches dynamic class bugs earlier than manual QA alone.
Key Takeaways
- Run
npx @tailwindcss/upgradefirst, then switch from PostCSS to@tailwindcss/viteon Vite 8 projects. - Replace
@tailwinddirectives with@import "tailwindcss"and move tokens into@themeblocks. - Declare Laravel Blade, pagination, and compiled view paths with
@sourceor styles will silently disappear. - Audit borders and focus rings — default border color and ring width changed between v3 and v4.
- Verify every community plugin has a version 4 release before merging to production.
- Commit built assets if production servers compile PHP only — the Oxide build still needs Node on CI.
People Also Ask
Is tailwind.config.js removed in Tailwind CSS 4?
It is optional, not removed. New projects configure design tokens in CSS through @theme. Existing JavaScript config files load via @config as a compatibility bridge. Plan to migrate tokens into CSS and delete the JS file once the bridge is empty.
Does Tailwind CSS 4 work with PostCSS only?
Yes. Install @tailwindcss/postcss if you cannot use the Vite plugin. The dedicated Vite integration is faster and recommended for Laravel 13 stacks. WordPress or legacy webpack setups may stay on PostCSS longer.
How long does a typical Tailwind CSS 4 migration take?
A small Laravel app with under fifty Blade files often completes in one to two days including visual QA. Large apps with custom plugins, multiple themes, or Bootstrap coexistence need a full sprint. The upgrade CLI handles most mechanical rewrites in minutes.
Can you use Tailwind CSS 4 with Bootstrap on the same page?
Technically yes, but avoid applying both frameworks to the same element. Prefix Tailwind utilities or scope them to a wrapper class. On legal-tech and portal projects I keep Bootstrap for the public site and Tailwind isolated to admin dashboards built with Vite.
Ship the upgrade with confidence
Tailwind CSS 4 What Changed and How to Migrate comes down to three moves: adopt the Oxide-powered build, rewrite configuration in CSS, and fix the small set of default visual changes that break silently. The upgrade CLI and Vite plugin remove most friction. Your time goes to QA, not config archaeology.
If you want help planning a Laravel, WordPress, or hybrid front-end upgrade, contact us for a migration assessment. We can audit your Blade templates, Vite pipeline, and plugin dependencies before you touch production. For related reading, explore essential Laravel packages, the testing and optimization service, and Mijar Law Associates for a live Laravel portal example.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

