Skip to content

Commit 1b9faf3

Browse files
committed
feat(skill): tailwind-impl-build-vite
1 parent e3c531c commit 1b9faf3

4 files changed

Lines changed: 1623 additions & 0 deletions

File tree

Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
---
2+
name: tailwind-impl-build-vite
3+
description: >
4+
Use when wiring Tailwind CSS into a Vite project: choosing between the
5+
v4 dedicated Vite plugin and the v3 PostCSS pipeline, picking the right
6+
packages and configs, importing the stylesheet, enabling HMR, and
7+
scoping template-scan paths in monorepos. Prevents the wrong-plugin
8+
trap (using postcss-plugin with v4 instead of @tailwindcss/vite gives
9+
much slower builds and broken at-rules), the broken-classnames trap
10+
(writing @import "tailwindcss" in v3 yields no utilities), the
11+
missing-content trap (v3 without content paths produces an empty
12+
stylesheet), the missing-source trap (v4 in a monorepo where workspace
13+
templates live outside the Vite root never get scanned), the upgrade
14+
trap (v4-0-8 Astro break, issue 16733), and the wrong-tool trap
15+
(chasing Turbopack issue 19825 in a Vite project). Covers v4 with
16+
@tailwindcss/vite (install, vite-config-ts plugin entry, @import
17+
"tailwindcss" in the entry CSS, automatic content detection,
18+
@source for monorepo/external paths, HMR), v3 with postcss-plugin
19+
(npm install -D tailwindcss postcss autoprefixer, npx tailwindcss
20+
init -p, postcss-config-js, tailwind-config-js content paths, the
21+
three @tailwind directives), framework-flavored Vite setups (React,
22+
Vue, Svelte, SolidJS, Astro, Qwik), library-mode and SSR notes,
23+
workspace and pnpm monorepo wiring, the v4-0-8 Astro regression
24+
workaround, and verifying that classnames actually generate CSS.
25+
Keywords: tailwind vite, @tailwindcss/vite, vite plugin tailwind,
26+
tailwind vite install, tailwind v4 vite, tailwind v3 vite,
27+
postcss tailwind vite, vite-config-ts plugin order, @import tailwindcss,
28+
@tailwind base components utilities, npx tailwindcss init -p,
29+
tailwind init vite, tailwind.config.js content paths, HMR tailwind,
30+
hot reload tailwind vite, monorepo tailwind vite, pnpm workspace
31+
tailwind, @source workspace, tailwind v4 monorepo, library mode
32+
tailwind, vite ssr tailwind, astro tailwind v4 broken, tailwind
33+
v4-0-8 break, classes not applying vite, no styles vite tailwind,
34+
empty stylesheet vite tailwind, where is tailwind.config v4,
35+
how to install tailwind in vite, getting started tailwind vite,
36+
styles missing after build, blank styles vite, vite plugin order
37+
tailwind, react vite tailwind, vue vite tailwind, svelte vite
38+
tailwind, solidjs vite tailwind, qwik vite tailwind, why nothing
39+
shows tailwind, my classes are not working tailwind vite.
40+
license: MIT
41+
compatibility: "Designed for Claude Code. Requires Tailwind CSS v3.4 or v4.0+."
42+
metadata:
43+
author: OpenAEC-Foundation
44+
version: "1.0"
45+
---
46+
47+
# Tailwind CSS Build Integration with Vite
48+
49+
Vite has two completely separate Tailwind integration paths:
50+
51+
- **v4** : the dedicated `@tailwindcss/vite` plugin (preferred for v4)
52+
- **v3** : the legacy `tailwindcss` PostCSS plugin (used via Vite's built-in PostCSS)
53+
54+
ALWAYS match plugin to version. NEVER use `@tailwindcss/postcss` with v4 inside
55+
Vite when `@tailwindcss/vite` is available : the dedicated plugin is faster,
56+
supports the v4 at-rules natively, and integrates with Vite's HMR and
57+
dependency graph.
58+
59+
Companion skills :
60+
61+
- `tailwind-impl-config-v3` : the v3 JS-config surface
62+
- `tailwind-impl-config-v4` : the v4 CSS-first config surface
63+
- `tailwind-core-v3-vs-v4` : behavioral differences between versions
64+
65+
## Quick Reference
66+
67+
### v4 with @tailwindcss/vite (preferred)
68+
69+
Install :
70+
71+
```bash
72+
npm install tailwindcss @tailwindcss/vite
73+
```
74+
75+
`vite.config.ts` :
76+
77+
```ts
78+
import { defineConfig } from "vite"
79+
import tailwindcss from "@tailwindcss/vite"
80+
81+
export default defineConfig({
82+
plugins: [
83+
tailwindcss(),
84+
],
85+
})
86+
```
87+
88+
`src/style.css` (entry stylesheet) :
89+
90+
```css
91+
@import "tailwindcss";
92+
```
93+
94+
Reference the entry stylesheet from your HTML or framework entry
95+
(`<link rel="stylesheet" href="/src/style.css">` for vanilla, `import
96+
"./style.css"` from `main.ts` for React/Vue/Svelte/SolidJS).
97+
98+
No `tailwind.config.js` is required. v4 auto-detects template files
99+
relative to the Vite root via `.gitignore` and source-scanner heuristics.
100+
101+
### v3 with PostCSS
102+
103+
Install :
104+
105+
```bash
106+
npm install -D tailwindcss@3 postcss autoprefixer
107+
npx tailwindcss init -p
108+
```
109+
110+
The `-p` flag also generates `postcss.config.js`. Vite reads it automatically.
111+
112+
`tailwind.config.js` :
113+
114+
```js
115+
/** @type {import('tailwindcss').Config} */
116+
export default {
117+
content: [
118+
"./index.html",
119+
"./src/**/*.{js,ts,jsx,tsx,vue,svelte}",
120+
],
121+
theme: {
122+
extend: {},
123+
},
124+
plugins: [],
125+
}
126+
```
127+
128+
`postcss.config.js` (generated by `init -p`) :
129+
130+
```js
131+
export default {
132+
plugins: {
133+
tailwindcss: {},
134+
autoprefixer: {},
135+
},
136+
}
137+
```
138+
139+
`src/index.css` :
140+
141+
```css
142+
@tailwind base;
143+
@tailwind components;
144+
@tailwind utilities;
145+
```
146+
147+
ALWAYS list every template extension you actually use in `content`.
148+
Anything not matched is invisible to the JIT scanner and produces no CSS.
149+
150+
## Decision Trees
151+
152+
### Which plugin should I use ?
153+
154+
```
155+
Tailwind major version ?
156+
├── v4 (4.0.0 and above)
157+
│ └── ALWAYS @tailwindcss/vite
158+
│ NEVER @tailwindcss/postcss in a Vite project
159+
│ NEVER the v3 tailwindcss postcss-plugin (it will not parse v4 at-rules)
160+
└── v3 (3.x)
161+
└── ALWAYS the tailwindcss postcss-plugin via postcss.config.js
162+
NEVER @tailwindcss/vite (it only exists for v4)
163+
```
164+
165+
### What entry CSS should I write ?
166+
167+
```
168+
Version ?
169+
├── v4 : @import "tailwindcss";
170+
│ (single line, no @tailwind directives)
171+
└── v3 : @tailwind base;
172+
@tailwind components;
173+
@tailwind utilities;
174+
(all three required, in this order)
175+
```
176+
177+
### My classes are not applying. Where do I look ?
178+
179+
```
180+
1. Is the entry CSS imported into the app entry ?
181+
├── No : add import "./style.css" in main.ts (or <link> in index.html)
182+
└── Yes : continue
183+
2. Is the Tailwind plugin registered in vite.config.ts (v4) or
184+
postcss.config.js (v3) ?
185+
├── No : add it
186+
└── Yes : continue
187+
3. v3 : does tailwind.config.js content include the files you write classes in ?
188+
├── No : add the glob (e.g. "./src/**/*.{ts,tsx}")
189+
└── Yes : continue
190+
4. v4 : are the files inside the Vite root, and not gitignored ?
191+
├── Outside root or gitignored : add @source "path"; in your entry CSS
192+
└── Yes : continue
193+
5. Are class names produced by string concatenation
194+
(e.g. "text-" + color) ?
195+
└── Yes : the JIT scanner cannot see them, use safelist
196+
(v3 safelist in config, v4 @source inline "{...}" brace expansion)
197+
6. Inspect the built CSS in DevTools : if utilities are missing,
198+
the scanner did not see your file. If present but not applied,
199+
it is a specificity or order issue, not a Tailwind setup issue.
200+
```
201+
202+
### Monorepo : how do I include workspace packages ?
203+
204+
```
205+
Version ?
206+
├── v3 : extend content paths in tailwind.config.js :
207+
│ content: [
208+
│ "./index.html",
209+
│ "./src/**/*.{ts,tsx,vue,svelte}",
210+
│ "../../packages/ui/src/**/*.{ts,tsx}",
211+
│ ],
212+
└── v4 : add @source entries to the entry CSS :
213+
@import "tailwindcss";
214+
@source "../../packages/ui/src/**/*.{ts,tsx}";
215+
(the v4 plugin auto-detects files only within the Vite root
216+
and respects .gitignore, so external packages need @source)
217+
```
218+
219+
## Patterns
220+
221+
### Pattern : framework-flavored Vite setup (v4)
222+
223+
For React (`@vitejs/plugin-react`), Vue (`@vitejs/plugin-vue`), Svelte
224+
(`@sveltejs/vite-plugin-svelte`), SolidJS (`vite-plugin-solid`), or Qwik :
225+
add `tailwindcss()` to the `plugins` array. Order does not matter for
226+
Tailwind's CSS pipeline, but ALWAYS keep the framework plugin first
227+
when a framework provides its own CSS preprocessor (Svelte, Vue) so
228+
component-scoped styles are parsed before Tailwind sees them.
229+
230+
```ts
231+
import { defineConfig } from "vite"
232+
import react from "@vitejs/plugin-react"
233+
import tailwindcss from "@tailwindcss/vite"
234+
235+
export default defineConfig({
236+
plugins: [
237+
react(),
238+
tailwindcss(),
239+
],
240+
})
241+
```
242+
243+
### Pattern : single-file CSS for v3 vs v4
244+
245+
v4 entry CSS :
246+
247+
```css
248+
@import "tailwindcss";
249+
250+
@theme {
251+
--color-brand: oklch(0.7 0.2 145);
252+
}
253+
```
254+
255+
v3 entry CSS :
256+
257+
```css
258+
@tailwind base;
259+
@tailwind components;
260+
@tailwind utilities;
261+
262+
@layer base {
263+
:root {
264+
--brand: 220 90% 56%;
265+
}
266+
}
267+
```
268+
269+
NEVER mix the two : the three v3 directives are silently ignored by v4,
270+
and `@import "tailwindcss"` is meaningless in v3.
271+
272+
### Pattern : HMR for design tokens
273+
274+
HMR works out of the box in both versions. Editing the entry CSS,
275+
`tailwind.config.js` (v3), or any file matched by content/`@source`
276+
triggers a stylesheet swap with no full reload. ALWAYS rely on this :
277+
NEVER write a custom Vite plugin to watch Tailwind files.
278+
279+
If HMR appears broken, the cause is almost always one of :
280+
281+
1. The file you edited is not in `content` (v3) or not in the Vite root
282+
without an `@source` entry (v4).
283+
2. A separate dev server proxy strips Vite's WebSocket connection.
284+
3. The browser cached the old stylesheet : hard-reload once.
285+
286+
### Pattern : library-mode and SSR
287+
288+
In `build.lib` mode, the Tailwind plugin still runs and emits the
289+
generated stylesheet alongside your library bundle. ALWAYS export the
290+
stylesheet path so consumers can import it. For SSR (`vite-node`, SvelteKit,
291+
Astro, Nuxt), the plugin runs once per build : no extra setup is needed
292+
beyond standard SSR-safe usage of the generated CSS.
293+
294+
## Anti-Patterns
295+
296+
NEVER install both `@tailwindcss/vite` and `@tailwindcss/postcss` in
297+
the same Vite project. They both transform CSS and double-process at-rules.
298+
299+
NEVER add `@tailwind base/components/utilities` to a v4 entry stylesheet.
300+
v4 ignores those directives. The single `@import "tailwindcss"` replaces all three.
301+
302+
NEVER write `@import "tailwindcss"` in a v3 entry. v3 has no such import
303+
target and will leave the line unresolved, producing zero utilities.
304+
305+
NEVER configure `content` in `tailwind.config.js` when using v4 with
306+
`@tailwindcss/vite`. The v4 scanner ignores the JS config unless you
307+
opt in via `@config`. Use `@source` directives in CSS instead.
308+
309+
NEVER set `optimizeDeps.exclude: ["tailwindcss"]` in `vite.config.ts`.
310+
It is a runtime non-issue and only slows the first dev start.
311+
312+
See `references/anti-patterns.md` for the full catalog with quoted
313+
error symptoms and fixes.
314+
315+
## Common Breakage
316+
317+
### v4.0.8 Astro regression (tailwindlabs/tailwindcss#16733)
318+
319+
Tailwind v4.0.8 + Astro + `@tailwindcss/vite` regressed parsing of
320+
component-package styles. Symptom : utilities that worked under 4.0.7
321+
silently stopped applying after upgrade.
322+
323+
ALWAYS pin to 4.0.7 OR upgrade past the patched release if you are on
324+
Astro + Vite and hit missing utilities right after a 4.0.8 bump :
325+
326+
```json
327+
"dependencies": {
328+
"tailwindcss": "4.0.7",
329+
"@tailwindcss/vite": "4.0.7"
330+
}
331+
```
332+
333+
### Turbopack arbitrary-value miss (tailwindlabs/tailwindcss#19825)
334+
335+
Issue 19825 reports arbitrary-value classes like `aspect-[12/5]`,
336+
`z-[100]`, `h-[80vh]` missing in Next.js + Turbopack builds.
337+
338+
This bug is Turbopack-specific. Vite users are NOT affected.
339+
If you are on Vite and arbitrary-value classes go missing, the cause
340+
is almost always a missing `@source` (v4) or content path (v3),
341+
NEVER this Turbopack bug.
342+
343+
## Verification
344+
345+
After install, ALWAYS verify with a single class that exercises the JIT :
346+
347+
```html
348+
<div class="text-3xl font-bold underline">Tailwind is wired</div>
349+
```
350+
351+
If the text becomes large, bold, and underlined in the dev server,
352+
the entire chain (plugin registered, entry CSS imported, scanner
353+
seeing your template) is working.
354+
355+
For arbitrary values, also try :
356+
357+
```html
358+
<div class="text-[#ff00aa] h-[42vh]">Arbitrary values</div>
359+
```
360+
361+
If arbitrary values fail but utility classes work, the JIT engine
362+
is running but content/source scope is wrong.
363+
364+
## Reference Links
365+
366+
- `references/methods.md` : exhaustive API of @tailwindcss/vite plugin
367+
options, v3 PostCSS options, init flags, package commands
368+
- `references/examples.md` : full project examples for React, Vue, Svelte,
369+
SolidJS, Astro, Qwik, both v3 and v4, plus monorepo and library-mode
370+
- `references/anti-patterns.md` : every known wiring mistake with the
371+
exact error or symptom, the cause, and the fix
372+
373+
## Sources
374+
375+
- v4 install for Vite : https://tailwindcss.com/docs/installation/using-vite
376+
- v3 install for Vite : https://v3.tailwindcss.com/docs/guides/vite
377+
- v4 directives reference : https://tailwindcss.com/docs/functions-and-directives
378+
- @tailwindcss/vite plugin : https://github.com/tailwindlabs/tailwindcss/tree/next/packages/%40tailwindcss-vite
379+
- v4.0.8 Astro regression : https://github.com/tailwindlabs/tailwindcss/issues/16733
380+
- Turbopack arbitrary-value miss (NOT Vite) : https://github.com/tailwindlabs/tailwindcss/issues/19825

0 commit comments

Comments
 (0)