The JavaScript configuration and plugin snippets here target Tailwind CSS 3. Tailwind CSS 4 uses CSS-first configuration; explicitly load a compatible legacy config with @config rather than assuming automatic discovery. Upgrade guide.
Tailwind's underlying generation mechanism & purge principle is the key to understanding "why writing this way is safe/efficient".
I will dismantle it for you according to the complete link of "From build → JIT → purge". This article is based on the background of Vite / Vue / compilation principle direction.
1. Overview of the overall process (first have the overall picture)
The general experience when building Tailwind is:
tailwind.config.js
↓
解析 theme / plugins
↓
生成“候选类名规则表”
↓
扫描 content(源码)
↓
JIT 即时生成 CSS
↓
输出最终 CSS📌 Key Points
- ❌ Not all classes are pre-generated
- ✅ Yes On-demand generation (JIT)
2. How does Tailwind JIT work?
1️⃣ Early days (before v2)
- Pre-generated tens of thousands of CSS
- It’s useless to purge again
- Slow build, large CSS
2️⃣ Now (v3+, default JIT)
core idea
See a class → generate a CSS immediately
For example:
<div class="px-4 text-red-500"></div>JIT will:
- split class token
- Matching rules
- Check theme value
- Generate CSS
.px-4 { padding-left: 1rem; padding-right: 1rem }
.text-red-500 { color: #ef4444 }3️⃣ Internal abstract model (important)
Each class = a "function call"
text-red-500
│ │ │
│ │ └── scale value
│ └────── theme key
└────────── utility nameEquivalent to:
text(color = theme.colors.red[500])📌 So Tailwind is very much like a DSL
3. Content scanning mechanism (the core of purge)
1️⃣ What is being scanned?
content: ['./src/**/*.{vue,js,ts,html}']Tailwind will:
- read file
- Use regular to extract possible class tokens
For example:
<div class="px-4 text-red-500"></div>will be split into:
px-4
text-red-5002️⃣ Key facts (many people don’t know)
Tailwind doesn’t understand JS/Vue syntax
It just scans "string"
📌 So 👇
❌
`bg-${color}-500`Scan results:
bg-
-color-
-500👉 Match failed → No CSS generated
4. Why are dynamic classes purged?
The reason is not purge, but:
JIT "cannot see the full class name" at all
For example:
<div :class="`bg-${type}-500`"></div>Tailwind scanned only:
bg-
-type-
-500So:
- No valid token
- Does not trigger generation
5. JIT token matching rules (very important)
Examples of valid tokens
bg-red-500
hover:bg-blue-500
md:hover:text-smInternal processing order
variants → utility → valueFor example:
md:hover:bg-red-500Equivalent to:
@media (min-width: 768px) {
.md\:hover\:bg-red-500:hover { background: ... }
}6. How do variants work?
Tailwind treats variants as "wrappers"
hover: → &:hover
md: → @media
dark: → .dark &So:
<div class="dark:hover:bg-gray-800"></div>Equivalent to:
.dark .dark\:hover\:bg-gray-800:hover {
background-color: #1f2937;
}7. Why are the classes generated by the plug-in not purged?
Reason:
Plugins inject rules before JIT
plugin
↓
addUtilities / addComponents
↓
规则表
↓
content 扫描📌 Classes in the plug-in:
- Belongs to "registered rules"
- No scan hits required
8. safelist (whitelist) mechanism
Used for: You know you want to use it, but it can’t be scanned
safelist: [
'bg-red-500',
'bg-blue-500',
{
pattern: /bg-(red|blue|green)-(100|500)/
}
]📌 Use with caution
- safelist = forced generation
- CSS will become larger if you use it too much
9. Why is Tailwind so small?
Because:
- Missed classes → not generated at all
- Useless variant → will not be included
- Plug-ins also take effect on demand
A Vue project:
- Actual CSS: 10~30KB
- rather than MB
10. Cooperation of Tailwind & Vite (you will resonate with it)
Why is Tailwind HMR so fast on Vite?
文件变更
↓
Vite 通知
↓
Tailwind 重新扫描这个文件
↓
增量生成 CSS📌 Not a full rebuild
This is essentially consistent with the Vite virtual module/HMR you studied.
11. The underlying explanation of common “weird bugs”
1️⃣ class is written but it has no effect
- Illegal spelling
- There is no such value in theme
- dynamically spliced
2️⃣ dev yes, build no
- content path is missing
- The production environment class is written differently
- Classes in dependent packages are not scanned
12. Comparison summary with your previous Vue/compilation direction
| Tailwind | Compilation principle analogy |
|---|---|
| utility | AST node |
| variant | wrapper |
| theme | symbol table |
| JIT | on-demand codegen |
| purge | dead code elimination |
📌 Tailwind Essence = CSS Compiler
13. Correctly using Tailwind’s “instructions”
- 1️⃣ Class name must be a static string
- 2️⃣ Design variables into theme/plugin
- 3️⃣ Complex dynamics → Mapping table
- 4️⃣ Public system → plug-in