Skip to main content

Tailwindcss 和其他 bootstrap.css 样式库有什么本质的区别?

· 3 min read

Tailwind 是构建时按需生成 CSS 的工具,不是预制类库。 这是它和 Bootstrap、iconfont 这类传统 class 库最本质的区别。

  • 本质区别:Bootstrap 是运行时可用的预制 CSS,Tailwind 是构建时扫源码生成
  • 类何时存在:Bootstrap 加载即用,Tailwind 必须被构建器扫到源码才生成
  • 体积策略:Bootstrap 固定(库大小决定),Tailwind 动态(你用多少决定)
  • 跨包坑点:monorepo 子包构建器只扫自己源码,看不到别的包用到的 class
  • 配置关键:tailwind.config.jscontent 必须覆盖到所有源码路径

你以为的 Tailwind 是什么

很多人第一次接触 Tailwind,会下意识把它当成另一种 Bootstrap:

  • bootstrap.css,或 iconfont
  • 库作者把所有类都预先写好
  • 页面运行时加载一次 CSS,直接用所有类名

Tailwind 默认不是这个模式。

我之前也这么以为——直到下游包产物里 class 集体消失,UI 散了一地,才意识到 Tailwind 根本不是 Bootstrap 的替代品,是另一种东西。

它实际是什么

Tailwind 是个 CSS 代码生成器,跑在构建流程里:

  1. 你在源码里写 className="flex h-full"
  2. 构建时扫描所有源码
  3. 只把出现过的类生成成 CSS

源码里没写的类,CSS 里就不会有。

为什么这么设计

Tailwind 的类名空间是组合爆炸的:

  • 间距:p-1p-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 库的本质区别

维度BootstrapTailwind
类何时存在库作者预先写好构建时按源码生成
体积固定(库大小决定)动态(你用多少决定)
跨包可见性加载即用必须被构建器扫到

最后一行最关键:传统类库是"运行时可用",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 集合。