前言
原子化 CSS(Atomic CSS)是近年来前端样式方案的重要趋势。从 Tailwind CSS 的一统天下,到 Windi CSS 的性能革新,再到 UnoCSS 的极致灵活——三者的演化折射出前端工程化对「DX(开发体验)」与「性能」的不懈追求。
本文将从概念起源、核心原理、横向对比、演化脉络四个维度,全面解析三大原子化 CSS 引擎。
一、原子化 CSS 的概念与起源
1.1 什么是原子化 CSS?
传统 CSS 按语义命名(如 .card-title、.user-avatar),而原子化 CSS 将样式拆解为最小粒度的单一功能类:
<!-- 传统 CSS -->
<div class="card-title">Hello</div>
<!-- 原子化 CSS -->
<div class="text-xl font-bold text-gray-800">Hello</div>
每个类只做一件事:text-xl 控制大小,font-bold 控制粗细,text-gray-800 控制颜色。
1.2 为什么需要原子化 CSS?
传统 CSS 的痛点:
- 命名困难:
.card-titlevs.card__titlevs.cardTitle?BEM、OOCSS、SMACSS 各种规范争战不休 - 样式冲突:全局作用域下,类名重复、优先级覆盖是家常便饭
- 死代码:项目迭代中,CSS 文件只增不减,大量未使用的样式堆积
- 包体积膨胀:CSS 随功能线性增长
原子化 CSS 的优势:
- 无需命名:直接用功能类组合
- 无冲突:原子类不依赖 DOM 结构
- 按需生成:只有用到的类才会被生成
- 天然摇树优化:不使用 = 不打包
1.3 起源:Functional CSS
原子化 CSS 思想起源于 2013 年左右的 Functional CSS(也叫 immuttable CSS),代表项目有 Tachyons、Basscss。它们预定义了大量原子类,但需要在 HTML 中组合使用。
<!-- Tachyons (2014) -->
<div class="f4 fw6 dark-gray">Hello</div>
缺点是:全量预定义,无论是否使用,所有类都会打包进 CSS,导致文件巨大(Tachyons 完整版 ~300KB)。
二、Tailwind CSS:打破僵局的先行者
2.1 核心理念
Tailwind CSS 于 2017 年由 Adam Wathan 发布,核心理念是 utility-first——用工具类构建 UI,而不写自定义 CSS。
2.2 核心特性
约束式设计系统
Tailwind 预定义了一套设计令牌(spacing、color、font-size 等),所有工具类基于这套约束生成:
// tailwind.config.js
module.exports = {
theme: {
spacing: {
0: '0px',
1: '0.25rem', // 4px
2: '0.5rem', // 8px
4: '1rem', // 16px
8: '2rem', // 32px
},
colors: {
gray: {
100: '#f7fafc',
800: '#2d3748',
}
}
}
}
使用时只能使用预定义的值:
<div class="p-4 text-gray-800">约東下的样式</div>
<div class="p-[13px]">也可以用任意值(JIT 模式)</div>
JIT 模式(v3.0+)
Tailwind v3 引入 Just-In-Time 编译器,移除了早期版本的混淆(purge)机制:
<!-- 任何在源文件中出现的类都会被即时生成 -->
<div class="grid grid-cols-[200px_minmax(900px,_1fr)_100px]">
自定义网格
</div>
JIT 的优势:
- 零等待:按需生成,不再全量生成后过滤
- 任意值:
w-[345px]、text-[#1da1f2]等不再需要配置 - 变体组合:
hover:dark:focus:bg-red-500可任意组合
插件生态
// tailwind.config.js
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
]
2.3 工作原理
Tailwind 使用 PostCSS 插件在构建时扫描源文件,匹配类名后生成对应 CSS:
源文件 → PostCSS 扫描 → 匹配类名 → 生成 CSS → 写入产出文件
扫描策略:
content: [
'./src/**/*.{html,js,ts,jsx,tsx,vue}',
'./components/**/*.{vue,js,ts}'
]
2.4 优缺点
优点:
- 生态成熟,社区庞大
- 插件丰富
- 文档详尽
- 设计约束强,适合团队统一规范
缺点:
- 构建速度慢:PostCSS 扫描 + 生成,大型项目 HMR 延迟明显
- 配置繁重:
tailwind.config.js在大型项目中可能上千行 - 框架耦合:与构建工具深度绑定,灵活性有限
三、Windi CSS:性能革命的开拓者
3.1 诞生背景
Windi CSS 于 2021 年发布,作者Forrest Liu 直指 Tailwind 的性能瓶颈:
"Tailwind 的 PostCSS 构建在大型项目中越来越慢,我们需要一个更快的替代品。"
3.2 核心特性
按需生成(On-demand)
Windi 不预生成任何 CSS,而是在运行时分析源文件,只生成实际使用到的类:
源文件 → AST 解析 → 提取类名 → 按需生成 CSS → 注入 HMR
预飞行(Preflight)
/* Windi 的 reset 样式自带在运行时 */
*,::before,::after { box-sizing: border-box; border: 0 solid; }
变体分组
<!-- Tailwind 写法 -->
<div class="hover:bg-gray-100 hover:text-gray-800 hover:font-bold md:flex md:flex-col">
<!-- Windi 变体分组 -->
<div class="hover:(bg-gray-100 text-gray-800 font-bold) md:(flex flex-col)">
扫描优化
Windi 使用自定义 AST 解析器替代正则扫描,准确度更高,速度更快。
3.3 性能对比
在大型项目中,Windi 的构建速度可达 Tailwind 的 20~100 倍:
| 项目规模 | Tailwind v2 (秒) | Windi (秒) |
|---|---|---|
| 小型 | 0.8s | 0.2s |
| 中型 | 3.5s | 0.3s |
| 大型 (1000+ 组件) | 12s | 0.5s |
3.4 兼容性
Windi 设计为 Tailwind 的严格超集,配置文件兼容,可直接迁移:
// windi.config.js / tailwind.config.js
export default {
theme: { /* 完全兼容 */ },
plugins: [/* 兼容 Tailwind 插件 */],
}
3.5 缺点与局限
- 维护停滞:2022 年后作者精力转向 UnoCSS,Windi 基本停止更新
- 配置复杂度:虽然兼容 Tailwind,但高级特性需要自己的配置方式
- 生态依赖:仍依赖 Tailwind 的插件生态,自身无单独插件体系
四、UnoCSS:极致灵活的引擎
4.1 设计哲学
UnoCSS 于 2021 年底由 Anthony Fu 发布。设计哲学是 "不是框架,是引擎"——不提供预设样式,而是提供规则引擎,让用户定义自己的原子类系统。
4.2 核心特性
规则即引擎
// uno.config.ts
import { defineConfig, presetUno } from 'unocss'
export default defineConfig({
presets: [presetUno()], // 类似 Tailwind 的预设
rules: [
// 自定义规则:类名 → CSS
['m-1', { margin: '0.25rem' }],
// 动态规则:正则匹配
[/^m-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
// 自定义属性
['card', { 'border-radius': '8px', padding: '16px' }],
]
})
预设系统
import { defineConfig } from 'unocss'
export default defineConfig({
presets: [
presetUno(), // Tailwind/Windi 兼容预设
presetAttributify(), // 属性化模式
presetIcons(), // 图标预设
presetTypography(), // 排版预设
presetWebFonts(), // 网络字体
presetWind(), // Tailwind v3 兼容
// presetContainerQueries(), // 容器查询
],
})
属性化模式
<!-- 原子类写法 -->
<div class="p-4 text-center text-gray-800">
<!-- UnoCSS attributify 写法 -->
<div p-4 text-center text-gray-800>
图标支持
<!-- 直接用类名引入任何图标库的图标 -->
<i class="i-mdi-account"></i>
<i class="i-logos-vue"></i>
<i class="i-carbon-sun dark:i-carbon-moon"></i>
原理:presetIcons 将图标 ID 映射到 CSS background-image,按需加载图标 SVG。
变体分组
<div class="hover:(bg-gray-100 text-gray-800) md:(flex flex-col)">
shortcuts:组合类
shortcuts: {
'btn': 'px-4 py-2 rounded inline-block cursor-pointer',
'btn-primary': 'btn bg-blue-500 text-white hover:bg-blue-600',
'btn-danger': 'btn bg-red-500 text-white hover:bg-red-600',
}
<button class="btn-primary">Primary Button</button>
自动按需变体
<!-- 不需要预设所有变体组合,按需生成 -->
<div class="dark:hover:focus:sm:bg-red-500">
任意变体组合
</div>
4.3 性能优势
UnoCSS 的构建过程不依赖 AST 解析,而是用正则提取 + 规则匹配的超快策略,构建速度比 Windi 还快 5x+:
| 引擎 | 构建速度 | CSS 大小 |
|---|---|---|
| Tailwind v3 | 1.2s | 8.5KB |
| Windi CSS | 0.3s | 7.8KB |
| UnoCSS | 0.05s | 5.2KB |
4.4 生态集成
UnoCSS 是构建工具无关的,支持:
// Vite
import UnoCSS from 'unocss/vite'
// Webpack
const UnoCSS = require('@unocss/webpack')
// PostCSS
const UnoCSS = require('@unocss/postcss')
// CLI
npx unocss 'src/**/*.html' -o build.css
// Nuxt
export default defineNuxtConfig({
modules: ['@unocss/nuxt']
})
五、三者横向对比
5.1 功能对比表
| 特性 | Tailwind CSS | Windi CSS | UnoCSS |
|---|---|---|---|
| 构建工具 | PostCSS 插件 | 自定义 AST | 独立引擎 + 插件 |
| 扫描方式 | 正则 | AST 解析 | 超快正则 |
| JIT 模式 | v3+ 支持 | 原生支持 | 原生支持 |
| 任意值 | [xxx] |
[*] |
[*] + 动态规则 |
| 变体分组 | ❌ | ✅ | ✅ |
| 属性化模式 | ❌ | ✅ | ✅ |
| 内置图标 | ❌ | ❌ | ✅ (presetIcons) |
| shortcuts | @apply | ✅ | ✅ |
| 自定义规则 | 配置主题 | 配置主题 | 规则引擎 + 预设 |
| 插件体系 | JS 插件 | 兼容 TW | 自成体系 |
| 框架集成 | 多框架 | 多框架 | 多框架 + 原生 |
| 构建速度 | 慢 | 快 | 最快 |
| CSS 体积 | 中 | 小 | 最小 |
| 维护状态 | 活跃维护 | 已停滞 | 活跃维护 |
5.2 设计理念对比
Tailwind : 一套完整的设计系统 + 工具类生成器
↓
Windi : 更快的 Tailwind 兼容替代品
↓
UnoCSS : 通用原子 CSS 引擎,一切皆规则
- Tailwind 适合:需要完整设计约束的团队项目
- Windi 适合:已用 Windi 的老项目(新项目不推荐)
- UnoCSS 适合:需要极致性能与灵活性的项目
六、演化脉络与未来趋势
6.1 时间线
2013 Tachyons / Basscss → Functional CSS 芳芽
↓
2017 Tailwind CSS v1 → Utility-first + 约束式设计系统
↓
2020 Tailwind CSS v2 → 混淆机制优化、暗色模式
↓
2021 Windi CSS → 按需生成 + 变体分组、超越性能
↓
2021 Tailwind CSS v3 → JIT 模式、任意值
↓
2021 UnoCSS → 引擎理念 + 预设 + 插件体系
↓
2023 Tailwind CSS v4 → Oxide 引擎(Rust 重写) + 性能 10x
↓
2024 UnoCSS → 容器查询、分层、可持续演进
6.2 Tailwind v4 的回应
Tailwind v4 用 Rust 重写了核心引擎 Oxide,构建速度提升了 10 倍以上,回应了 UnoCSS 的性能挑战:
// @tailwindcss/vite (v4)
import tailwindcss from '@tailwindcss/vite'
export default {
plugins: [tailwindcss()]
}
面向配置零化:
/* 不需要 tailwind.config.js,直接在 CSS 中用 @theme */
@import "tailwindcss";
@theme {
--color-my-blue: #1da1f2;
--spacing-my-1: 0.375rem;
}
6.3 趋势观察
- 引擎竞赛:构建速度已经不是瓶颈,三者都在秒下级别
- 配置零化:Tailwind v4 去掉 JS 配置,UnoCSS 零配置启动
- 跨工具兼容:UnoCSS 的 presetWind 兼容 Tailwind v4 语法
- 生态融合:Tailwind 插件可以被 UnoCSS 预设复用
- DX 优先:属性化、变体分组、shortcuts 等成为标配
七、选型建议
7.1 新项目选型
| 场景 | 推荐 |
|---|---|
| React/Next.js 生态 | Tailwind CSS v4 |
| Vue/Nuxt 生态 | UnoCSS |
| 需要图标 + 属性化 + 分组 | UnoCSS |
| 需要严格设计约束 | Tailwind CSS |
| 极致性能追求 | UnoCSS |
| 已有 Tailwind 项目升级 | Tailwind v4 或注移 UnoCSS |
7.2 迁移建议
从 Tailwind 迁移到 UnoCSS:
// 1. 安装 UnoCSS
pnpm add -D unocss @unocss/preset-wind
// 2. 配置文件
import { defineConfig, presetWind, presetAttributify, presetIcons } from 'unocss'
export default defineConfig({
presets: [
presetWind(), // Tailwind 兼容预设
presetAttributify(),
presetIcons(),
],
// 复用原主题配置
theme: {
colors: { /* tailwind.config.js colors */ },
spacing: { /* tailwind.config.js spacing */ }
}
})
// 3. Vite 配置
import UnoCSS from 'unocss/vite'
export default {
plugins: [UnoCSS()]
}
大多数类名可直接复用,变体写法兼容。
八、总结
三大原子化 CSS 引擎反映了前端样式方案的三个阶段:
- Tailwind CSS:开创 utility-first 范式,以约束式设计系统定义了一代人写 CSS 的方式
- Windi CSS:以性能革命推动 Tailwind 迭代 JIT,虽衰灭火但其精神延续
- UnoCSS:以引擎理念超越框架,规则驱动的无穷可能让原子 CSS 更上层楼
三者并非单纯竞争关系,而是相互促动:Windi 推动 Tailwind 引入 JIT,UnoCSS 推动Tailwind v4 用 Rust 重写引擎。这种良性竞争最终造福了整个前端生态。
选择哪个不是关键,理解原子化 CSS 的核心思想——用功能粒度代替语义粒度——才是最重要的。在这个基础上,无论是 Tailwind、UnoCSS 还是未来可能出现的新引擎,都只是具体实现。
延伸阅读:
Comments | 0条评论