{"id":67,"date":"2026-07-14T13:00:00","date_gmt":"2026-07-14T07:30:00","guid":{"rendered":"https:\/\/softcrony.com\/blog\/?p=67"},"modified":"2026-07-14T13:00:00","modified_gmt":"2026-07-14T07:30:00","slug":"tailwind-css-v4-whats-new-migration","status":"publish","type":"post","link":"https:\/\/softcrony.com\/blog\/tailwind-css-v4-whats-new-migration\/","title":{"rendered":"Tailwind CSS v4: What&#8217;s New and How to Migrate Your Project"},"content":{"rendered":"<p>Tailwind CSS v4 is a ground-up rewrite of the framework \u2014 new engine, new configuration, new syntax for some features, and dramatically improved performance. If you&#8217;re on v3, here&#8217;s what you need to know.<\/p>\n<h2>What&#8217;s New in Tailwind CSS v4<\/h2>\n<h3>1. New High-Performance Engine (Oxide)<\/h3>\n<p>Tailwind v4 ships with a new Rust-based engine called Oxide. Build times are dramatically faster:<\/p>\n<table>\n<thead>\n<tr>\n<th>Project Size<\/th>\n<th>v3 Build Time<\/th>\n<th>v4 Build Time<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Small (50 components)<\/td>\n<td>1.2s<\/td>\n<td>0.1s<\/td>\n<\/tr>\n<tr>\n<td>Medium (200 components)<\/td>\n<td>4.8s<\/td>\n<td>0.3s<\/td>\n<\/tr>\n<tr>\n<td>Large (500+ components)<\/td>\n<td>18s<\/td>\n<td>1.1s<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>2. CSS-First Configuration<\/h3>\n<p>The biggest change \u2014 configuration moves from <code>tailwind.config.js<\/code> to CSS:<\/p>\n<pre><code>\/* v3 \u2014 tailwind.config.js *\/\r\nmodule.exports = {\r\n  theme: {\r\n    extend: {\r\n      colors: {\r\n        primary: '#3b82f6',\r\n        secondary: '#64748b',\r\n      },\r\n      fontFamily: {\r\n        sans: ['Inter', 'sans-serif'],\r\n      },\r\n    },\r\n  },\r\n};<\/code><\/pre>\n<pre><code>\/* v4 \u2014 app.css *\/\r\n@import \"tailwindcss\";\r\n\r\n@theme {\r\n  --color-primary: #3b82f6;\r\n  --color-secondary: #64748b;\r\n  --font-sans: 'Inter', sans-serif;\r\n}<\/code><\/pre>\n<p>Your custom values are now CSS variables \u2014 which means you can read and modify them in JavaScript too.<\/p>\n<h3>3. Zero Configuration by Default<\/h3>\n<p>v4 auto-detects your template files \u2014 no <code>content<\/code> array needed:<\/p>\n<pre><code>\/* v3 \u2014 required content config *\/\r\nmodule.exports = {\r\n  content: [\r\n    '.\/src\/**\/*.{js,jsx,ts,tsx}',\r\n    '.\/pages\/**\/*.{js,jsx,ts,tsx}',\r\n  ],\r\n};\r\n\r\n\/* v4 \u2014 nothing needed, auto-detected *\/\r\n@import \"tailwindcss\"; \/* That's it *\/<\/code><\/pre>\n<h3>4. Native CSS Cascade Layers<\/h3>\n<p>v4 uses native CSS <code>@layer<\/code> \u2014 no more specificity fighting with third-party styles:<\/p>\n<pre><code>\/* v4 outputs proper cascade layers *\/\r\n@layer theme { ... }\r\n@layer base { ... }\r\n@layer components { ... }\r\n@layer utilities { ... }<\/code><\/pre>\n<h3>5. New Utilities in v4<\/h3>\n<pre><code>&lt;!-- Container queries (no plugin needed) --&gt;\r\n&lt;div class=\"@container\"&gt;\r\n  &lt;div class=\"@sm:grid-cols-2 @lg:grid-cols-4\"&gt;...&lt;\/div&gt;\r\n&lt;\/div&gt;\r\n\r\n&lt;!-- 3D transforms (new) --&gt;\r\n&lt;div class=\"rotate-x-45 rotate-y-12 perspective-500\"&gt;...&lt;\/div&gt;\r\n\r\n&lt;!-- Field sizing (new) --&gt;\r\n&lt;textarea class=\"field-sizing-content\"&gt;&lt;\/textarea&gt;\r\n\r\n&lt;!-- Color mixing (new) --&gt;\r\n&lt;div class=\"bg-blue-500\/75\"&gt;...&lt;\/div&gt;\r\n\r\n&lt;!-- Dynamic values without config --&gt;\r\n&lt;div class=\"mt-[13px] bg-[#1a2b3c] grid-cols-[1fr_2fr_1fr]\"&gt;...&lt;\/div&gt;<\/code><\/pre>\n<h2>Breaking Changes from v3<\/h2>\n<h3>Removed in v4<\/h3>\n<pre><code>&lt;!-- v3 \u2014 no longer works in v4 --&gt;\r\n&lt;div class=\"shadow-sm\"&gt;...&lt;\/div&gt;     &lt;!-- renamed --&gt;\r\n&lt;div class=\"ring-offset-2\"&gt;...&lt;\/div&gt; &lt;!-- syntax changed --&gt;\r\n&lt;div class=\"decoration-slice\"&gt;...&lt;\/div&gt; &lt;!-- removed --&gt;<\/code><\/pre>\n<h3>Renamed Classes<\/h3>\n<table>\n<thead>\n<tr>\n<th>v3 Class<\/th>\n<th>v4 Class<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>shadow-sm<\/code><\/td>\n<td><code>shadow-xs<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>shadow<\/code><\/td>\n<td><code>shadow-sm<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>ring-offset-{n}<\/code><\/td>\n<td><code>outline-offset-{n}<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>overflow-ellipsis<\/code><\/td>\n<td><code>text-ellipsis<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>flex-shrink<\/code><\/td>\n<td><code>shrink<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>flex-grow<\/code><\/td>\n<td><code>grow<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>decoration-clone<\/code><\/td>\n<td><code>box-decoration-clone<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>How to Migrate from v3 to v4<\/h2>\n<h3>Step 1 \u2014 Run the Upgrade Tool<\/h3>\n<pre><code>npx @tailwindcss\/upgrade<\/code><\/pre>\n<p>This automated tool handles most of the migration:<\/p>\n<ul>\n<li>Updates your CSS imports<\/li>\n<li>Migrates <code>tailwind.config.js<\/code> to CSS <code>@theme<\/code><\/li>\n<li>Renames changed utility classes across your template files<\/li>\n<li>Updates PostCSS configuration<\/li>\n<\/ul>\n<h3>Step 2 \u2014 Install v4<\/h3>\n<pre><code>npm install tailwindcss@next @tailwindcss\/vite\r\n\r\n# Or with PostCSS\r\nnpm install tailwindcss@next @tailwindcss\/postcss<\/code><\/pre>\n<h3>Step 3 \u2014 Update Vite Config<\/h3>\n<pre><code>\/\/ vite.config.ts\r\nimport { defineConfig } from 'vite';\r\nimport tailwindcss from '@tailwindcss\/vite';\r\n\r\nexport default defineConfig({\r\n  plugins: [\r\n    tailwindcss(), \/\/ replaces the PostCSS plugin\r\n  ],\r\n});<\/code><\/pre>\n<h3>Step 4 \u2014 Update CSS Entry Point<\/h3>\n<pre><code>\/* Before (v3) *\/\r\n@tailwind base;\r\n@tailwind components;\r\n@tailwind utilities;\r\n\r\n\/* After (v4) *\/\r\n@import \"tailwindcss\";\r\n\r\n@theme {\r\n  \/* your custom tokens here *\/\r\n  --color-primary: #3b82f6;\r\n}<\/code><\/pre>\n<h3>Step 5 \u2014 Migrate Custom Plugins<\/h3>\n<p>If you have custom Tailwind plugins, they need updating for v4&#8217;s new API:<\/p>\n<pre><code>\/* v3 plugin *\/\r\nconst plugin = require('tailwindcss\/plugin');\r\n\r\nmodule.exports = plugin(function({ addUtilities }) {\r\n  addUtilities({\r\n    '.text-balance': { 'text-wrap': 'balance' },\r\n  });\r\n});\r\n\r\n\/* v4 \u2014 just write it in CSS *\/\r\n@utility text-balance {\r\n  text-wrap: balance;\r\n}<\/code><\/pre>\n<h2>Should You Migrate Now?<\/h2>\n<p>For <strong>new projects<\/strong> \u2014 yes, start with v4. The performance and DX improvements are significant and you&#8217;ll avoid a migration later.<\/p>\n<p>For <strong>existing projects<\/strong> \u2014 depends on size and risk tolerance:<\/p>\n<ul>\n<li>Small project (under 50 components): migrate now, takes 1\u20132 hours<\/li>\n<li>Medium project: run the upgrade tool, plan a day for manual fixes<\/li>\n<li>Large project with custom plugins: plan carefully, test thoroughly, migrate in a branch<\/li>\n<\/ul>\n<p>If you need help migrating a large React or Laravel project from Tailwind v3 to v4, <a href=\"https:\/\/softcrony.com\/contact\/\">our frontend team at Softcrony can handle it<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tailwind CSS v4 is a ground-up rewrite of the framework \u2014 new engine, new configuration, new syntax for some features, and dramatically improved performance. If you&#8217;re on v3, here&#8217;s what you need to know. What&#8217;s New in Tailwind CSS v4 1. New High-Performance Engine (Oxide) Tailwind v4 ships with a new Rust-based engine called Oxide. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":68,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[70,51,48,69,18],"class_list":["post-67","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-frontend","tag-css","tag-frontend","tag-react","tag-tailwind-css","tag-web-development"],"_links":{"self":[{"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/comments?post=67"}],"version-history":[{"count":1,"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":69,"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions\/69"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/media\/68"}],"wp:attachment":[{"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/media?parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/categories?post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/softcrony.com\/blog\/wp-json\/wp\/v2\/tags?post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}