三份可直接双击打开的案例页、一个同屏对比页、一批本机实测数据——聊聊三种 CSS 框架的设计哲学、样式能力、交互成本和选型边界。
![图片[1]-同一套 UI,三种写法:Bootstrap / Bulma / Tailwind 三框架横评-西城知道](https://028.sevenit.cn/wordpress/2026/10/20261016125054949-另起一行广告传媒_2026-10-16_12-50-41.jpg)
![图片[4]-同一套 UI,三种写法:Bootstrap / Bulma / Tailwind 三框架横评-西城知道](https://028.sevenit.cn/wordpress/2026/10/20261016125711485-另起一行广告传媒_2026-10-16_12-56-30.jpg)
一、这篇文章从哪来
手上有三份”讲同一件事”的页面:它们都演示布局、排版、表单、组件、工具类、暗黑模式这几块内容,但分别用 Bootstrap、Bulma、Tailwind CSS 实现。既然内容对等,就正好可以当成一次控制变量的横评。
为了对比方便,我又做了两件事:
- 把三份页面塞进同一个
index.html:三栏iframe并排/堆叠、可缩放、可按章节跳转、可同步滚动,样式互不污染; - 把结论写成这篇文章,并附上可复现的测量方法(见文末)。
文件清单如下。
| 文件 | 框架与版本 | 说明 |
|---|---|---|
index.html |
— | 同屏对比页:三栏 iframe + 功能矩阵 + 代码对照(不含本文,本文单独成页) |
bootstrap-showcase.html |
Bootstrap 5.3.8 | 组件全家桶,交互由官方 bundle 驱动,含 icons 与暗黑模式 |
bulma-showcase.html |
Bulma 1.0.4 | 纯 CSS,交互为 183 行自写 JS,含 v1 的 grid 与 skeleton |
tailwind-showcase.html |
Tailwind 4.3.3 | 原子化工具类拼装,交互为 197 行自写 JS |
三份页面结构上刻意对齐,覆盖的模块数量如下:
| 页面 | 章节 | 行数 | 自写 JS | 自定义 CSS |
|---|---|---|---|---|
| Bootstrap | 布局 / 排版 / 图片表格 / 组件 / 表单 / 工具 | 1088 | 80 行 | 43 行 |
| Bulma | 布局 / 元素 / 组件 / 表单 / 辅助 / 特性 | 1306 | 183 行 | 57 行 |
| Tailwind | 布局 / 排版 / 颜色 / 按钮 / 表单 / 组件 / 工具 | 873 | 197 行 | 3 行 + 314 处 dark: |
最后一行已经剧透了三个框架的性格:Bootstrap 用别人的 JS,Bulma 用别人的 CSS,Tailwind 什么都不给你但什么都能写。
二、三种设计哲学:你买到的”交付物”不一样
Bootstrap:把组件当一等公民。 它交付的是一套完整的 UI 套件——按钮、卡片、模态框、下拉、轮播、Toast、Offcanvas、Tooltip……每个组件既有样式也有行为,行为由官方 JS 插件驱动。你用 data-bs-toggle 写声明,剩下的(焦点陷阱、ESC 关闭、滚动锁、ARIA 状态同步)框架全包。
Bulma:把语义化类名当一等公民。 它只交付 CSS,一个字节 JS 都没有。类名高度可读(button is-primary is-outlined、has-text-danger、is-size-3),v1 之后全面变量化(--bulma-*),顺带内置了暗黑模式的变量切换和 is-skeleton 骨架屏。代价是:交互、图标、Toast 这类”行为”要你自己接。
Tailwind:把设计 token + 原子类当一等公民。 它交付的是一台编译器:你写 px-4 py-2 rounded-lg bg-sky-600,它按需生成对应的 CSS。没有”按钮”这个概念,只有零件。好处是产物最小、约束最统一;代价是模板变长、组件体系要自己长出来(或引入 shadcn/Headless UI 这类无样式组件库)。
三、同一个按钮,三种写法
<!-- Bootstrap:语义类组合,改颜色改尺寸都只是换类名 -->
<button type="button" class="btn btn-primary">主要按钮</button>
<button type="button" class="btn btn-outline-primary btn-sm">描边小按钮</button>
<button type="button" class="btn btn-primary" disabled>禁用</button>
<!-- Bulma:读起来最像英文句子 -->
<button class="button is-primary">主要按钮</button>
<button class="button is-outlined is-small">描边小按钮</button>
<button class="button is-primary" disabled>禁用</button>
<!-- Tailwind:一次写完所有细节,复用要靠组件化 -->
<button class="rounded-lg bg-sky-600 px-4 py-2 text-sm font-medium text-white
transition hover:bg-sky-500 disabled:cursor-not-allowed disabled:opacity-50">
主要按钮
</button>
三行代码背后是三种维护模型:Bootstrap 改一次 --bs-primary 全局生效;Bulma 改一次 --bulma-primary 全局生效;Tailwind 要靠设计 token 和组件封装,否则你会在一个项目里看到 7 种蓝色。
四、样式能力:栅格、间距、颜色、排版
| 对比项 | Bootstrap | Bulma | Tailwind |
|---|---|---|---|
| 栅格 | 12 列 flex 栅格,offset/order/gutter 齐全 | columns(12 等分 flex)+ v1 grid(CSS Grid) |
原生 Grid/Flex 任意拼装,grid-cols-12、gap-4 |
| 间距刻度 | m/p-0~5 六档 + auto |
m/p-0~6 七档 |
0.25rem 基准的任意倍数,p-13 也合法 |
| 颜色 | 8 个语义色 + subtle/emphasis/rgb 变体 | 6 个语义色 + light/dark/invert/on-* 派生 | 22+ 色板 × 11 阶,支持任意值 |
| 排版 | display-*、lead、fs-*、fw-* |
title、subtitle、is-size-* |
text-*、font-*、leading-*、tracking-* |
| 圆角阴影 | 够用 | 偏少,常需自定义 | 全套 + 任意值 |
| 写一套新皮肤 | 低(SCSS / CSS 变量) | 低(--bulma-* 变量) |
中(要自己定义并贯穿 token) |
一句话总结:Bootstrap 提供”够用的刻度”,Bulma 提供”好读的刻度”,Tailwind 提供”没有刻度的尺子”。 刻度少的好处是设计一致性天然更好;刻度自由的好处是不用为了 13px 的间距去写一个自定义类。
五、组件覆盖:这是最大的分水岭
我把三份页面里演示过的组件整理成 24 类,逐个核对:
| 组件 | Bootstrap | Bulma | Tailwind |
|---|---|---|---|
| 按钮 / 按钮组 | ✅ 内置 | ✅ 内置 | ⚠️ flex 拼装 |
| 卡片 | ✅ | ✅ | ⚠️ |
| 模态框 | ✅ + 官方 JS | ✅ 结构 + 自写 JS | ⚠️ 自绘 + 自写 JS |
| 下拉菜单 | ✅ 官方 JS | ✅ + 自写 JS | ⚠️ + 自写 JS |
| 标签页 | ✅ 官方 JS | ✅ + 自写 JS | ⚠️ role=tablist 自写 |
| 手风琴 / 折叠 | ✅ | ⚠️ 自写 | ⚠️ 自写 |
| 轮播 | ✅ | ❌ | ⚠️ 自写 |
| Toast 通知 | ✅ | ⚠️ 只有静态 notification | ⚠️ 自写 + aria-live |
| 进度条 | ✅ 含条纹/动画 | ✅ | ⚠️ |
| 分页 | ✅ | ✅ 含 ellipsis | ⚠️ |
| 面包屑 | ✅ | ✅ 含 is-arrowed | ⚠️ |
| 徽章 / 标签 | ✅ | ✅ 可删除 tag | ⚠️ |
| 列表组 / 面板 / 消息块 | ✅ list-group | ✅ panel / message / menu | ⚠️ |
| 侧滑面板 | ✅ offcanvas | ❌ | ⚠️ |
| 提示 / 气泡 | ✅ tooltip + popover | ❌ | ⚠️ |
| 骨架屏 | ✅ placeholder | ✅ is-skeleton(v1) | ⚠️ animate-pulse |
| 导航栏(含汉堡) | ✅ 官方 JS | ✅ + 自写 JS | ⚠️ |
| 表格 | ✅ | ✅ | ⚠️ |
| 表单校验态 | ✅ | ✅ | ⚠️ 自绘 |
| 浮动标签 | ✅ form-floating | ⚠️ 自写 | ⚠️ peer 技巧 |
| 输入组 / 前后缀 | ✅ | ✅ 图标型 | ⚠️ |
| 开关 switch | ✅ | ⚠️ | ⚠️ |
| 文件上传 | ✅ | ✅ 组件较完整 | ⚠️ |
| 滑块 / 多选下拉 | ✅ | ⚠️ | ⚠️ |
统计结果:Bootstrap 24 类全部开箱即用;Bulma 16 类有现成样式(5 类要自己拼、3 类没有);Tailwind 一类都没有。
这就是三个框架最本质的差别:Bootstrap 卖组件,Bulma 卖样式,Tailwind 卖零件。如果你的页面里塞满了模态框、下拉、轮播、Toast,选 Bootstrap 省下的工作量是以”天”计算的;如果页面基本是内容展示,Bulma 的语义化类名会让 HTML 好读很多。
六、交互:谁在替你写 JavaScript
| 交互成本 | Bootstrap | Bulma | Tailwind |
|---|---|---|---|
| 交互实现者 | 官方 bundle(79 KB / gzip 23.3 KB) | 你自己 | 你自己 |
| 案例页自写 JS | 80 行(基本只有主题切换) | 183 行 | 197 行 |
| 声明式交互 | ✅ data-bs-toggle="modal" |
❌ | ❌ |
| ARIA 状态同步 | 插件自动 | 手写 | 手写 |
| 键盘支持(ESC / Tab / 方向键) | 框架内置 | 手写 | 手写 |
有个很直观的对照:三份页面里都有”下拉菜单、标签页、模态框、导航栏汉堡菜单、主题切换”这五组交互。
- Bootstrap 版只写了 80 行 JS,其中大部分还是主题切换——因为交互全部由插件接管;
- Bulma 版和 Tailwind 版分别写了 183 行和 197 行,因为连
aria-expanded和is-active的切换都得自己来。
判断法则:如果页面里超过 5 个交互组件,Bootstrap 的 79 KB JS 是划算的;如果只有一两个(比如一个移动端菜单),那 190 行自写 JS 换来的”零 JS 依赖”更干净。
七、暗黑模式:三条完全不同的路线
| 路线 | Bootstrap | Bulma | Tailwind |
|---|---|---|---|
| 机制 | data-bs-theme="dark" |
data-theme="dark" 覆盖 --bulma-* |
.dark class + dark: 变体 |
| 切换代码 | 一行 setAttribute |
一行 setAttribute |
一行 classList.toggle |
| 逐元素适配 | 不需要 | 不需要(自定义组件用变量即可) | 314 处 dark: |
| 可控粒度 | 整套变量 | 整套变量 | 任意元素 |
| 主要坑 | 自定义 CSS 要用 --bs-* 变量 |
v0 没有变量体系,v1 才补齐 | class 变长,token 不统一就会花 |
暗黑模式其实是判断一个框架”是否设计系统化”的试纸。Bootstrap 和 Bulma 的做法是”换一套变量”,你写业务样式时只要用变量,切换就是零成本;Tailwind 的做法是”每个元素写两遍”,控制力最强,但三份页面里它是唯一需要 314 处额外类名的那份——这不是 Tailwind 的缺陷,而是它的模型:它把主题决策的负担从框架转移到了你的模板和团队约定上。
八、体积:真实数字
以下数据在本机实测(方法见文末),原始体积按 CDN 上的 min 版本统计,gzip 为 level 9。
| 资源 | 原始 | gzip |
|---|---|---|
| Bootstrap 5.3.8 CSS | 227 KB | 30.0 KB |
| Bootstrap 5.3.8 bundle JS | 79 KB | 23.3 KB |
| Bootstrap Icons CSS(另有字体文件) | 84 KB | 12.9 KB |
| Bulma 1.0.4 CSS | 662 KB | 63.5 KB |
| Tailwind 4.3.3 浏览器版运行时 | 276 KB | 72.1 KB |
| Tailwind 为案例页按需生成的 CSS | 53 KB | 8.4 KB |
| 同上,minify 后(≈生产产物) | 42 KB | 7.8 KB |
| Bootstrap CSS + JS + 图标合计 | 390 KB | 66.2 KB |
三点解读:
- gzip 之后,Bootstrap 全家桶(66 KB)和 Bulma 单个 CSS(63.5 KB)几乎同级,但 Bootstrap 多送 24 类可交互组件。Bulma 的 662 KB 原始体积来自 v1 把 light/dark 两套配色变量全量吐出——网络成本能接受,但 CSS 解析不是免费的,移动端低端机要留意。
- Tailwind 浏览器版是体验工具,不是生产方案:276 KB 的运行时要在浏览器里现场编译,首次渲染会闪一下,而且需要较新的浏览器(Chrome 111+ / Safari 16.4+)。生产环境应当走构建流程,只为用到的类生成 CSS——本案例页按需生成 53 KB,minify 后 42 KB(gzip 仅 7.8 KB),这才是 Tailwind 真正的体积形态:同样的页面,CSS 网络成本只有 Bootstrap 全家桶的约 1/8、Bulma 的约 1/8。
- 三份案例页自身的 HTML 都在 60 KB 左右(1088 / 1306 / 873 行),因为大头是中文示例文案和表格内容,框架差异被内容淹没了——这也是个好提醒:框架体积焦虑要先看内容体积。
九、响应式与断点
| 框架 | 断点档位 | 写法 |
|---|---|---|
| Bootstrap | 6 档:576 / 768 / 992 / 1200 / 1400 | col-12 col-md-6 col-lg-4,断点内建在栅格类里 |
| Bulma | 5 档:769 / 1024 / 1216 / 1408(+ mobile) | columns is-multiline + 修饰类,或 v1 的 grid |
| Tailwind | 5 档:640 / 768 / 1024 / 1280 / 1536,可自定义 | 前缀即断点:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 |
写起来最顺手的是 Tailwind(任何工具类都能加断点前缀,不必是”栅格专属”);最省心的是 Bootstrap(栅格类自带断点,不需要你记断点数值);Bulma 的断点基于 min-width,从 tablet 才开始生效,写移动优先时需要适应一下它的心智模型。
十、可访问性:框架替你做了多少
- Bootstrap:插件会自动维护
aria-expanded、aria-selected、aria-controls,模态框有焦点陷阱、ESC 关闭、滚动锁,还有visually-hidden、RTL 支持。这一栏它领先得最多。 - Bulma / Tailwind:框架只提供样式,ARIA 全凭自觉。不过我核对过三份案例页——Bulma 版补了
aria-expanded、aria-selected、aria-hidden与focus-visible描边;Tailwind 版手写了role="tablist"、role="dialog"、aria-modal、aria-live、role="switch"+aria-checked。也就是说两份都补齐了,差别在于“谁保证不漏”:Bootstrap 是框架保证,另两个是代码评审保证。
如果你在做面向公众、有合规要求的项目,把可访问性检查写进 CI(例如 axe-core),比选哪个框架更重要。
十一、工程化与长期维护
| 对比项 | Bootstrap | Bulma | Tailwind |
|---|---|---|---|
| 是否必须构建 | 否 | 否 | 生产建议构建 |
| 按需裁剪 | 需自行用 SCSS 编译 | 需自行用 Sass 编译 | 天生按需生成 |
| 主题定制入口 | SCSS 变量 / --bs-* |
Sass 变量 / --bulma-* |
@theme 设计 token |
| 大版本升级风险 | 4 → 5 有破坏性变更 | 0.x → 1.0 变更较大 | 3 → 4 改为 CSS-first 配置 |
| 生态 | 极大(后台模板、企业项目多) | 中等 | 极大(Headless UI / Radix / shadcn) |
| 代码可读性 | 好,模板干净 | 最好 | 一般,需要组件化约束 |
| 学习曲线 | 低 | 低 | 中 |
| AI / 脚手架友好度 | 高 | 中 | 高(但依赖团队 token 约定) |
两个容易被忽略的点:
- Bootstrap 的”约定”既是资产也是负债。它的类名体系让新人一天就能上手,但也让所有 Bootstrap 站点长得像亲戚;想彻底摆脱”Bootstrap 味”,你得改 SCSS 变量、重写圆角阴影,成本并不低。
- Tailwind 的长期成本在约定,不在语法。它没有帮你做任何设计决策:色板要选、间距刻度要定、组件要封装(
cva、clsx、@apply或 React 组件)。没有这层约定,半年后的模板会变成一堵 class 墙。
十二、选型建议
| 场景 | 推荐 | 理由 |
|---|---|---|
| 后台管理系统、内部工具 | Bootstrap | 组件最多,表格/表单/模态框一次到位,交付最快 |
| 官网、落地页、内容型页面 | Bulma 或 Tailwind | 页面以展示为主,Bootstrap 的 JS 用不上 |
| 有设计稿、要还原度、长期迭代的 C 端产品 | Tailwind | token 化 + 任意值,最贴近设计系统 |
| 团队 CSS 弱、只想少写样式和 JS | Bulma | 语义化类名 + 零 JS,读起来就像 HTML |
| 快速原型 / Demo 给客户看 | Bootstrap 或 Tailwind + shadcn | 出效果最快 |
| 老项目增量改造 | Bootstrap 单组件定制,或 Tailwind 局部引入 | 都能按模块引入,不必整体迁移 |
| 追求极致首屏性能的静态站 | Tailwind 构建产物 | 只为用到的类生成 CSS,可压到最小 |
三条经验法则:
- 交互组件数量决定 Bootstrap 的性价比——超过 5 个可交互组件,它几乎稳赢。
- 设计独特性要求决定 Tailwind 的价值——如果产品必须”不像任何模板”,Tailwind 的自由度就是刚需。
- 团队 CSS 水平与维护周期决定 Bulma 是否够用——页面简单、人手少,它最省心;要长期演进的组件体系,它容易碰到天花板。
也可以混着用:Tailwind 写页面 + Headless UI/Radix 管交互;Bootstrap 只定制 SCSS 变量当组件库;Bulma 配少量自写 JS 做轻量站点。框架不是阵营,是成本结构。
十三、结论
三份页面演示的是同一批 UI,但把它们并排放在一起时,差别不在”哪个更好看”,而在你把成本付给了谁:
- Bootstrap 让你把成本付给体积和”同质化”,换回组件与交互;
- Bulma 让你把成本付给自写 JS 和自建组件,换回干净可读的 HTML;
- Tailwind 让你把成本付给模板长度与团队约定,换回最小的产物和最大的设计自由。
如果今天要重做这套案例页:交互密集的管理后台我会选 Bootstrap;内容型站点选 Bulma;有设计系统、要长期演进的产品选 Tailwind。没有最好的框架,只有最合适的约束。
附:怎么复现
查看对比页
- 双击
index.html:三栏 iframe 会自动加载三份案例页(首次需联网拉 CDN)。 - 顶部工具栏可以切换「并排 / 堆叠」、勾选显示哪几个框架、缩放 50%~100%、切换本页暗黑模式。
- 每列下方是章节跳转按钮、刷新按钮和”新窗口打开”。
- 「同步滚动」需要同源环境:在
file://下浏览器禁止跨文档访问,页面会自动提示降级。用同目录的启动本地服务.cmd以http://localhost:8931/打开即可启用同步滚动与章节即时跳转。
测量方法
- 体积:用 Node 从 jsdelivr 拉取对应版本文件,统计原始字节与 gzip(level 9)字节。
- Tailwind 生产形态:用 Edge 无头浏览器打开
tailwind-showcase.html,等浏览器端编译完成后提取注入的样式表,再用 lightningcss 压缩得到上面的数字。 - 行数 /
dark:计数:脚本统计三份 HTML 的行数与正则匹配数量。
数据采集于 2026-10-16,版本为当日 CDN 最新稳定版:Bootstrap 5.3.8、Bulma 1.0.4、Tailwind CSS 4.3.3,三者均为 MIT 许可。















![表情[daku]-西城知道](https://blog.ccswust.org/wp-content/themes/zibll/img/smilies/daku.gif)



暂无评论内容