To migrate from Tailwind CSS 3 to 4, start with a separate branch and the official upgrade tool, then verify build integration, configuration, and visual changes. Version 4 changes more than utility names: PostCSS and CLI integrations use separate packages, configuration can live in CSS, and browser support requirements matter.
Start with compatibility and a baseline
Read the official upgrade guide before changing dependencies. The upgrade tool requires Node.js 20 or newer. Confirm that v4’s browser requirements fit your audience, record your current package versions, and capture representative screens before migrating.
git switch -c upgrade-tailwind-v4
npx @tailwindcss/upgrade
Review the resulting diff before merging. A successful command does not prove that custom plugins, design tokens, and every interaction still work. The examples below use the v4 CSS syntax used by this site’s Tailwind 4.1.18 build; check current documentation for later minor-version additions.
Choose the correct build integration
| Build system | v4 package | Where it belongs |
|---|---|---|
| Vite | @tailwindcss/vite | Vite plugin configuration |
| PostCSS / Next.js | @tailwindcss/postcss | PostCSS configuration |
| Command-line build | @tailwindcss/cli | Your CSS build command |
For a PostCSS project, a minimal setup looks like this. Keep other plugins only if your project still needs them; do not blindly copy a configuration from a different framework.
// postcss.config.mjs
export default {
plugins: { '@tailwindcss/postcss': {} },
};
Move from directives to a CSS import
/* v3 entry point */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* v4 entry point: replace the three directives above */
@import "tailwindcss";
@theme {
--color-brand-600: #c25328;
--font-display: Georgia, serif;
}
Theme variables define the values used by generated utilities. Keep tokens that describe the brand separate from page-specific exceptions. Our design customization guide explains why those choices matter more than adding a different border radius to every card.
Check renamed utilities and changed defaults
Review shadows, border colors, rings, gradients, opacity modifiers, and any custom utility definitions. Compare the rendered result rather than assuming every old class has the same visual meaning. The official migration guide includes the detailed mapping; keep that reference beside the diff.
<!-- Example: color opacity -->
<div class="bg-black/50">…</div>
<!-- Example: linear gradient in v4 -->
<div class="bg-linear-to-r from-orange-100 to-amber-50">…</div>
Verify source detection
Classes assembled from arbitrary string fragments can be missed by a static scanner. Keep complete utility names in source, or map allowed values to complete class strings. Check shared packages and files outside the usual source tree. The source-detection documentation explains explicit source registration and exclusions.
Do not use the browser CDN as a production migration
The browser package is useful for quick experiments, but the Play CDN is intended for development. A production project should generate its CSS through the chosen build integration. Replacing a script URL is not a substitute for checking configuration and building the application.
A release checklist
- Run the production build, not only the development server.
- Compare mobile and desktop screenshots of forms, menus, dialogs, and long content.
- Test the actual dark-mode strategy used by your project.
- Check keyboard focus styles and disabled controls.
- Confirm that exported or dynamically loaded content has the CSS it needs.
- Keep a rollback commit until the migrated build has been verified.
Use the navbar example and loading-state example as small interaction checks. For new page layouts, browse reviewed design examples and verify their dependencies before integration.
