Tailwind CSS v4 With Vite: The Clean Setup That Drops Old Boilerplate
A practical Tailwind CSS v4 and Vite guide that shows the modern plugin-based setup, what changed from older Tailwind installs, and how to avoid dragging obsolete config habits into a newer stack.
Why this setup trips people up: many developers learned Tailwind on older versions, then copy old guides into a newer project and end up with unnecessary config, wrong plugin wiring, or a mental model that no longer matches the tool.
The old habit
People remember Tailwind as:
- install multiple packages
- create a big config file immediately
- edit content globs before the app even renders
That used to be normal. In newer setups, especially with Vite and Tailwind v4, the path can be much leaner.
Install the package
In a Vite project:
pnpm add tailwindcss @tailwindcss/viteYou can do the equivalent with npm or yarn if the repo uses those, but do not mix package managers casually inside one project.
Wire the Vite plugin
In vite.config.ts:
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [tailwindcss()],
});That is the key shift many older tutorials do not show.
Import Tailwind in your CSS
In your main stylesheet:
@import "tailwindcss";That is much simpler than the older layered directive setup many people still copy from memory.
Why developers think it is not working
Usually one of these is true:
- they followed an outdated guide
- the CSS file is not actually imported by the app entrypoint
- they edited a config pattern they did not need in the first place
- the dev server was not restarted after setup changes
The second issue is especially common. Tailwind can be installed correctly and still appear invisible if the stylesheet itself never enters the application bundle.
A clean verification step
Add a class-heavy test block:
export function Demo() {
return (
<div className="min-h-screen bg-slate-950 text-white p-8">
<button className="rounded-xl bg-cyan-400 px-4 py-2 font-semibold text-slate-950">
Tailwind is working
</button>
</div>
);
}If the page still looks plain, inspect the CSS import path before doing anything more complicated.
The bigger lesson
Frontend toolchains evolve faster than people’s tutorial memory. A lot of setup pain is not caused by the current tool at all. It is caused by carrying old boilerplate into a newer version because it once worked.
That is why “I already know Tailwind” can be a misleading assumption. You may know an older install story, not the current one.
Final recommendation
With Tailwind v4 and Vite, start from the modern plugin path and keep the setup small until the app is clearly rendering styles. Do not import old boilerplate just because it feels familiar. Familiar and current are not the same thing.
That is the broader frontend lesson too. Tooling changes quickly, and old setup muscle memory ages faster than most developers admit. A clean current setup is usually easier to maintain than a nostalgic one.
That is especially true in teams where setup instructions get copied from repo to repo. Once one outdated pattern enters the culture, it spreads faster than people update it. Starting from the current minimal path saves more maintenance than most developers expect.
That makes current documentation worth trusting more than old muscle memory.