Tailwind CSS 4.0: move configuration into CSS without losing control

Migrate a small theme to CSS, wire the correct build adapter, and check browser support, source detection, and changed defaults.
The migration starts with the build boundary
Tailwind CSS 4.0 shipped on 22 January 2025. Its CSS-first configuration and automatic source detection reduce setup, but an existing application still needs an explicit migration plan. The relevant questions are which tool processes the stylesheet, where templates live, and which browsers the product must support.
The v4 upgrade guide targets Safari 16.4+, Chrome 111+, and Firefox 128+. Check those requirements before changing a mature application. A successful build says nothing about whether a required browser can render the generated CSS correctly. The examples below target the original v4 configuration model, not every feature added in later minor releases.
Choose one integration for the application
In v4, the PostCSS integration is the separate @tailwindcss/postcss package. A project already using PostCSS can configure that adapter. Vite projects also have a dedicated @tailwindcss/vite integration. Do not copy a Vite configuration into an unrelated build or retain two competing Tailwind transformations.
This is a minimal PostCSS example. It assumes compatible tailwindcss and @tailwindcss/postcss packages are already installed and that the application imports the CSS entry. Preserve unrelated plugins that the application actually needs; this file is not an instruction to delete them.
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
Theme variables create the utility vocabulary
The @theme directive connects CSS custom properties to Tailwind utilities. A color token named --color-brand-600 makes utilities such as bg-brand-600 and text-brand-600 available. An ordinary custom property under :root remains useful CSS, but it does not automatically define a Tailwind utility family.
Keep the first migration small: one brand color and one display font are enough to verify the path. The fallback fonts below keep the example usable without downloading a font. The @source path is an illustrative shared component directory relative to this stylesheet; include it only if that directory exists in your project.
@import "tailwindcss";
@source "../../packages/ui/src";
@theme {
--color-brand-600: #2455cc;
--font-display: "Avenir Next", "Segoe UI", sans-serif;
}
.page-heading {
font-family: var(--font-display);
color: var(--color-brand-600);
}
Automatic detection still needs complete class names
Source detection can discover templates without a hand-maintained content array, but it cannot infer every string assembled at runtime. A fragment such as a color name concatenated into a utility is not a reliable contract with the scanner. Use complete class strings in a finite mapping when a component has a known set of variants.
Shared packages and unusual directory layouts also need attention. If a component renders correctly in one application but loses styles in another, verify which sources each build scans. Make that relationship explicit rather than adding unrelated utilities to an application template merely to keep them in the output.
Existing JavaScript configuration is not automatically detected in v4. If a staged migration retains it, use the documented compatibility mechanism and review which settings remain supported. A configuration file sitting in the repository is not proof that the build reads it.
Compare behavior, not just generated file size
Review borders, rings, shadows, form controls, and hover behavior against the upgrade guide. Changed defaults can produce subtle regressions even when every class compiles. Capture representative states before migrating: empty forms, validation errors, keyboard focus, open menus, and narrow layouts.
For verification, build the production CSS with the project’s existing command, inspect one generated brand utility, and test the same screens in supported browsers. Keep a distinct checkpoint for the build adapter change before broad visual cleanup. That makes failures easier to attribute.
CSS-first configuration is useful when the theme, utilities, and ordinary CSS become easier to inspect together. It is less useful if migration hides source paths or changes the browser contract without review. Accept the upgrade when the team can explain where a utility comes from and demonstrate that required interactions still work.

