Tailwindcss 和其他 bootstrap.css 样式库有什么本质的区别?
· 3 min read
Tailwind 是构 建时按需生成 CSS 的工具,不是预制类库。 这是它和 Bootstrap、iconfont 这类传统 class 库最本质的区别。
- 本质区别:Bootstrap 是运行时可用的预制 CSS,Tailwind 是构建时扫源码生成
- 类何时存在:Bootstrap 加载即用,Tailwind 必须被构建器扫到源码才生成
- 体积策略:Bootstrap 固定(库大小决定),Tailwind 动态(你用多少决定)
- 跨包坑点:monorepo 子包构建器只扫自己源码,看不到别的包用到的 class
- 配置关键:
tailwind.config.js的content必须覆盖到所有源码路径
你以为的 Tailwind 是什么
很多人第一次接触 Tailwind,会下意识把它当成另一种 Bootstrap:
- 像
bootstrap.css,或 iconfont - 库作者把所有类都预先写好
- 页面运行时加载一次 CSS,直接用所有类名
Tailwind 默认不是这个模式。
我之前也这么以为——直到下游包产物里 class 集体消失,UI 散了一地,才意识到 Tailwind 根本不是 Bootstrap 的替代品,是另一种东西。
它实际是什么
Tailwind 是个 CSS 代码生成器,跑在构建流程里:
- 你在源码里写
className="flex h-full" - 构建时扫描所有源码
- 只把出现过的类生成成 CSS
源码里没写的类,CSS 里就不会有。
为什么这么设计
Tailwind 的类名空间是组合爆炸的:
- 间距:
p-1到p-96 - 宽高:
w-*、h-* - 响应式:
sm:md:lg: - 状态:
hover:focus: - 暗色:
dark: - 任意值:
w-[123px]grid-cols-[1fr_2fr]
全量预生成 CSS 体积会大到夸张(几十 MB)。所以 Tailwind 选择按需生成——你用什么,构建器就生成什么。
实际产物对比
源码:
<div className="flex h-full w-screen text-foreground" />
构建后大致生成:
.flex { display: flex; }
.h-full { height: 100%; }
.w-screen { width: 100vw; }
.text-foreground { color: var(--color-foreground); }
源码里没写的 h-72,最终 CSS 里就不会出现。
和传统 class 库的本质区别
| 维度 | Bootstrap | Tailwind |
|---|---|---|
| 类何时存在 | 库作者预先写好 | 构建时按源码生成 |
| 体积 | 固定(库大小决定) | 动态(你用多少决定) |
| 跨包可见性 | 加载即用 | 必须被构建器扫到 |
最后一行最关键:传统类库是"运行时可用",Tailwind 是"构建时已生成"。
跨包场景的坑
这也是 Tailwind 在 monorepo 跨包里最容易卡住的地方:
- 假设
a-lib构建时只能扫描a-lib自己的源码 - 它看不到
b/c/d里用到的 class - 所以这些下游 repo 自己产出的 CSS 里,不会有它们内部用到的 utility class
很多人以为是 class 没定义对,其实是构建器没扫到源码——class 还在 a-lib 里,但没被复制到 b 的产物。
解决办法:把整个 monorepo 的源码路径都加到 content 配置里(通常写 **/*.{ts,tsx,html} 这种 glob),让构建器能扫到所有用到的 class。
一句话总结
Tailwind 是"扫描你的源码 → 生成最小的 CSS",不是"加载一份现成的大 CSS 库"。
把它当 Bootstrap 用,会得到一个空的 class 集合。