| name | tailwind-impl-build-vite |
| description | Use when wiring Tailwind CSS into a Vite project: choosing between the v4 dedicated Vite plugin and the v3 PostCSS pipeline, picking the right packages and configs, importing the stylesheet, enabling HMR, and scoping template-scan paths in monorepos. Prevents the wrong-plugin trap (using postcss-plugin with v4 instead of @tailwindcss/vite gives much slower builds and broken at-rules), the broken-classnames trap (writing @import "tailwindcss" in v3 yields no utilities), the missing-content trap (v3 without content paths produces an empty stylesheet), the missing-source trap (v4 in a monorepo where workspace templates live outside the Vite root never get scanned), the upgrade trap (v4-0-8 Astro break, issue 16733), and the wrong-tool trap (chasing Turbopack issue 19825 in a Vite project). Covers v4 with @tailwindcss/vite (install, vite-config-ts plugin entry, @import "tailwindcss" in the entry CSS, automatic content detection, @source for monorepo/external paths, HMR), v3 with postcss-plugin (npm install -D tailwindcss postcss autoprefixer, npx tailwindcss init -p, postcss-config-js, tailwind-config-js content paths, the three @tailwind directives), framework-flavored Vite setups (React, Vue, Svelte, SolidJS, Astro, Qwik), library-mode and SSR notes, workspace and pnpm monorepo wiring, the v4-0-8 Astro regression workaround, and verifying that classnames actually generate CSS. Keywords: tailwind vite, @tailwindcss/vite, vite plugin tailwind, tailwind vite install, tailwind v4 vite, tailwind v3 vite, postcss tailwind vite, vite-config-ts plugin order, @import tailwindcss, @tailwind base components utilities, npx tailwindcss init -p, tailwind init vite, tailwind.config.js content paths, HMR tailwind, hot reload tailwind vite, monorepo tailwind vite, pnpm workspace tailwind, @source workspace, tailwind v4 monorepo, library mode tailwind, vite ssr tailwind, astro tailwind v4 broken, tailwind v4-0-8 break, classes not applying vite, no styles vite tailwind, empty stylesheet vite tailwind, where is tailwind.config v4, how to install tailwind in vite, getting started tailwind vite, styles missing after build, blank styles vite, vite plugin order tailwind, react vite tailwind, vue vite tailwind, svelte vite tailwind, solidjs vite tailwind, qwik vite tailwind, why nothing shows tailwind, my classes are not working tailwind vite.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires Tailwind CSS v3.4 or v4.0+. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
Tailwind CSS Build Integration with Vite
Vite has two completely separate Tailwind integration paths:
- v4 : the dedicated
@tailwindcss/vite plugin (preferred for v4)
- v3 : the legacy
tailwindcss PostCSS plugin (used via Vite's built-in PostCSS)
ALWAYS match plugin to version. NEVER use @tailwindcss/postcss with v4 inside
Vite when @tailwindcss/vite is available : the dedicated plugin is faster,
supports the v4 at-rules natively, and integrates with Vite's HMR and
dependency graph.
Companion skills :
tailwind-impl-config-v3 : the v3 JS-config surface
tailwind-impl-config-v4 : the v4 CSS-first config surface
tailwind-core-v3-vs-v4 : behavioral differences between versions
Quick Reference
v4 with @tailwindcss/vite (preferred)
Install :
npm install tailwindcss @tailwindcss/vite
vite.config.ts :
import { defineConfig } from "vite"
import tailwindcss from "@tailwindcss/vite"
export default defineConfig({
plugins: [
tailwindcss(),
],
})
src/style.css (entry stylesheet) :
@import "tailwindcss";
Reference the entry stylesheet from your HTML or framework entry
(<link rel="stylesheet" href="/src/style.css"> for vanilla, import "./style.css" from main.ts for React/Vue/Svelte/SolidJS).
No tailwind.config.js is required. v4 auto-detects template files
relative to the Vite root via .gitignore and source-scanner heuristics.
v3 with PostCSS
Install :
npm install -D tailwindcss@3 postcss autoprefixer
npx tailwindcss init -p
The -p flag also generates postcss.config.js. Vite reads it automatically.
tailwind.config.js :
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx,vue,svelte}",
],
theme: {
extend: {},
},
plugins: [],
}
postcss.config.js (generated by init -p) :
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
src/index.css :
@tailwind base;
@tailwind components;
@tailwind utilities;
ALWAYS list every template extension you actually use in content.
Anything not matched is invisible to the JIT scanner and produces no CSS.
Decision Trees
Which plugin should I use ?
Tailwind major version ?
├── v4 (4.0.0 and above)
│ └── ALWAYS @tailwindcss/vite
│ NEVER @tailwindcss/postcss in a Vite project
│ NEVER the v3 tailwindcss postcss-plugin (it will not parse v4 at-rules)
└── v3 (3.x)
└── ALWAYS the tailwindcss postcss-plugin via postcss.config.js
NEVER @tailwindcss/vite (it only exists for v4)
What entry CSS should I write ?
Version ?
├── v4 : @import "tailwindcss";
│ (single line, no @tailwind directives)
└── v3 : @tailwind base;
@tailwind components;
@tailwind utilities;
(all three required, in this order)
My classes are not applying. Where do I look ?
1. Is the entry CSS imported into the app entry ?
├── No : add import "./style.css" in main.ts (or <link> in index.html)
└── Yes : continue
2. Is the Tailwind plugin registered in vite.config.ts (v4) or
postcss.config.js (v3) ?
├── No : add it
└── Yes : continue
3. v3 : does tailwind.config.js content include the files you write classes in ?
├── No : add the glob (e.g. "./src/**/*.{ts,tsx}")
└── Yes : continue
4. v4 : are the files inside the Vite root, and not gitignored ?
├── Outside root or gitignored : add @source "path"; in your entry CSS
└── Yes : continue
5. Are class names produced by string concatenation
(e.g. "text-" + color) ?
└── Yes : the JIT scanner cannot see them, use safelist
(v3 safelist in config, v4 @source inline "{...}" brace expansion)
6. Inspect the built CSS in DevTools : if utilities are missing,
the scanner did not see your file. If present but not applied,
it is a specificity or order issue, not a Tailwind setup issue.
Monorepo : how do I include workspace packages ?
Version ?
├── v3 : extend content paths in tailwind.config.js :
│ content: [
│ "./index.html",
│ "./src/**/*.{ts,tsx,vue,svelte}",
│ "../../packages/ui/src/**/*.{ts,tsx}",
│ ],
└── v4 : add @source entries to the entry CSS :
@import "tailwindcss";
@source "../../packages/ui/src/**/*.{ts,tsx}";
(the v4 plugin auto-detects files only within the Vite root
and respects .gitignore, so external packages need @source)
Patterns
Pattern : framework-flavored Vite setup (v4)
For React (@vitejs/plugin-react), Vue (@vitejs/plugin-vue), Svelte
(@sveltejs/vite-plugin-svelte), SolidJS (vite-plugin-solid), or Qwik :
add tailwindcss() to the plugins array. Order does not matter for
Tailwind's CSS pipeline, but ALWAYS keep the framework plugin first
when a framework provides its own CSS preprocessor (Svelte, Vue) so
component-scoped styles are parsed before Tailwind sees them.
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import tailwindcss from "@tailwindcss/vite"
export default defineConfig({
plugins: [
react(),
tailwindcss(),
],
})
Pattern : single-file CSS for v3 vs v4
v4 entry CSS :
@import "tailwindcss";
@theme {
--color-brand: oklch(0.7 0.2 145);
}
v3 entry CSS :
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--brand: 220 90% 56%;
}
}
NEVER mix the two : the three v3 directives are silently ignored by v4,
and @import "tailwindcss" is meaningless in v3.
Pattern : HMR for design tokens
HMR works out of the box in both versions. Editing the entry CSS,
tailwind.config.js (v3), or any file matched by content/@source
triggers a stylesheet swap with no full reload. ALWAYS rely on this :
NEVER write a custom Vite plugin to watch Tailwind files.
If HMR appears broken, the cause is almost always one of :
- The file you edited is not in
content (v3) or not in the Vite root
without an @source entry (v4).
- A separate dev server proxy strips Vite's WebSocket connection.
- The browser cached the old stylesheet : hard-reload once.
Pattern : library-mode and SSR
In build.lib mode, the Tailwind plugin still runs and emits the
generated stylesheet alongside your library bundle. ALWAYS export the
stylesheet path so consumers can import it. For SSR (vite-node, SvelteKit,
Astro, Nuxt), the plugin runs once per build : no extra setup is needed
beyond standard SSR-safe usage of the generated CSS.
Anti-Patterns
NEVER install both @tailwindcss/vite and @tailwindcss/postcss in
the same Vite project. They both transform CSS and double-process at-rules.
NEVER add @tailwind base/components/utilities to a v4 entry stylesheet.
v4 ignores those directives. The single @import "tailwindcss" replaces all three.
NEVER write @import "tailwindcss" in a v3 entry. v3 has no such import
target and will leave the line unresolved, producing zero utilities.
NEVER configure content in tailwind.config.js when using v4 with
@tailwindcss/vite. The v4 scanner ignores the JS config unless you
opt in via @config. Use @source directives in CSS instead.
NEVER set optimizeDeps.exclude: ["tailwindcss"] in vite.config.ts.
It is a runtime non-issue and only slows the first dev start.
See references/anti-patterns.md for the full catalog with quoted
error symptoms and fixes.
Common Breakage
v4.0.8 Astro regression (tailwindlabs/tailwindcss#16733)
Tailwind v4.0.8 + Astro + @tailwindcss/vite regressed parsing of
component-package styles. Symptom : utilities that worked under 4.0.7
silently stopped applying after upgrade.
ALWAYS pin to 4.0.7 OR upgrade past the patched release if you are on
Astro + Vite and hit missing utilities right after a 4.0.8 bump :
"dependencies": {
"tailwindcss": "4.0.7",
"@tailwindcss/vite": "4.0.7"
}
Turbopack arbitrary-value miss (tailwindlabs/tailwindcss#19825)
Issue 19825 reports arbitrary-value classes like aspect-[12/5],
z-[100], h-[80vh] missing in Next.js + Turbopack builds.
This bug is Turbopack-specific. Vite users are NOT affected.
If you are on Vite and arbitrary-value classes go missing, the cause
is almost always a missing @source (v4) or content path (v3),
NEVER this Turbopack bug.
Verification
After install, ALWAYS verify with a single class that exercises the JIT :
<div class="text-3xl font-bold underline">Tailwind is wired</div>
If the text becomes large, bold, and underlined in the dev server,
the entire chain (plugin registered, entry CSS imported, scanner
seeing your template) is working.
For arbitrary values, also try :
<div class="text-[#ff00aa] h-[42vh]">Arbitrary values</div>
If arbitrary values fail but utility classes work, the JIT engine
is running but content/source scope is wrong.
Reference Links
references/methods.md : exhaustive API of @tailwindcss/vite plugin
options, v3 PostCSS options, init flags, package commands
references/examples.md : full project examples for React, Vue, Svelte,
SolidJS, Astro, Qwik, both v3 and v4, plus monorepo and library-mode
references/anti-patterns.md : every known wiring mistake with the
exact error or symptom, the cause, and the fix
Sources