WSの小屋

前言

在原子化 CSS 的世界里,Tailwind CSS 已经成为了事实标准。然而,随着项目规模的扩大和开发体验需求的提升,Tailwind 在灵活性、扩展性和按需生成能力上的局限逐渐显现。UnoCSS 作为一颗冉冉升起的新星,以其"引擎而非框架"的核心理念,为我们提供了一种全新的原子化 CSS 解决方案。

UnoCSS 是由 Anthony Fu 开发的即时按需原子化 CSS 引擎。它的核心理念是:不预设任何样式,只提供引擎。 所有的样式规则通过预设(presets)和规则(rules)动态生成,让开发者拥有完全的控制权。


一、UnoCSS 的核心架构

层级 说明 对应概念
引擎层 负责匹配规则、生成 CSS、处理 HMR UnoCSS core
规则层 定义从类名到 CSS 的映射关系 rules / shortcuts
预设层 一组规则、变体、快捷方式的集合 presets

引擎本身不包含任何 CSS 规则,所有功能都通过预设加载。这意味着你可以完全定制属于你的原子化 CSS 体系。


二、规则系统详解

2.1 静态规则

rules: [
  ['m-0', { margin: '0px' }],
  ['m-1', { margin: '0.25rem' }],
  ['text-center', { 'text-align': 'center' }],
]

2.2 动态规则

rules: [
  // 间距规则: m-4, m-8, m-12...
  [/^m-(\d+)$/, ([, num]) => ({ margin: `${num * 0.25}rem` })],

  // 方向间距: mt-4, mr-2, mb-8...
  [/^([mtp])-(\d+)$/, ([, dir, num]) => {
    const dirs = { m: 'margin', t: 'margin-top', p: 'padding' }
    return { [dirs[dir]]: `${num * 0.25}rem` }
  }],

  // 任意值: w-[100px], h-[50vh]
  [/^w-\[(.+)\]$/, ([, val]) => ({ width: val })],
  [/^h-\[(.+)\]$/, ([, val]) => ({ height: val })],

  // 颜色: text-red-500, bg-blue-400
  [/^text-(\w+)-(\d+)$/, ([, color, shade]) => ({
    color: `var(--${color}-${shade})`,
  })],
]

2.3 规则的完整签名

rules: [
  [
    /^grid-cols-(\d+)$/,
    ([, num], { theme }) => ({
      'grid-template-columns': `repeat(${num}, minmax(0, 1fr))`,
    }),
    { layer: 'utilities', autocomplete: 'grid-cols-(1-12)' },
  ],
]

2.4 规则的匹配顺序

规则匹配是有序的——从上到下,第一个匹配到的规则胜出。最佳实践:将更具体的规则放在前面,更通用的动态规则放在后面。


三、变体系统

3.1 内置变体

<div class="hover:text-blue-500 active:text-red-500"></div>
<div class="md:text-lg lg:text-xl"></div>
<div class="dark:bg-gray-800"></div>
<div class="md:hover:text-blue-500 dark:hover:bg-gray-700"></div>

3.2 自定义变体

variants: [
  // 自定义 RTL 变体
  (matcher) => {
    if (!matcher.startsWith('rtl:')) return matcher
    return { matcher: matcher.slice(4), selector: s => `[dir="rtl"] ${s}` }
  },
  // 自定义打印变体
  (matcher) => {
    if (!matcher.startsWith('print:')) return matcher
    return { matcher: matcher.slice(6), selector: s => `@media print { ${s} }` }
  },
]

四、预设生态系统

4.1 presetWind(Tailwind 兼容)

import { defineConfig, presetWind } from 'unocss'
export default defineConfig({ presets: [presetWind()] })

4.2 presetAttributify(属性化模式)

<!-- 属性化方式 -->
<button bg="blue-500 hover:blue-600" text="white" p="x-4 y-2" rounded="lg">按钮</button>

4.3 presetIcons(图标预设)

<i class="i-mdi-home text-2xl"></i>
<i class="i-logos-vue text-3xl"></i>
<i class="i-carbon-sun dark:i-carbon-moon"></i>

UnoCSS 会在构建时按需下载图标集并内联为 SVG data URL,零运行时开销。

4.4 presetTypography(排版预设)

<article class="prose prose-lg dark:prose-invert">
  <h1>文章标题</h1>
  <p>这是一段正文内容...</p>
</article>

五、Shortcuts(快捷方式)

shortcuts: [
  // 静态快捷方式
  {
    'btn': 'px-4 py-2 rounded-lg font-medium transition-colors',
    'btn-primary': 'btn bg-blue-500 text-white hover:bg-blue-600',
    'card': 'bg-white dark:bg-gray-800 rounded-lg shadow-md p-6',
  },
  // 动态快捷方式
  [/^btn-(\w+)$/, ([, color]) => `btn bg-${color}-500 text-white hover:bg-${color}-600`],
]

六、与 Tailwind CSS 的核心差异

特性 Tailwind CSS UnoCSS
生成方式 预定义扫描 + JIT 按需动态生成
扩展性 配置文件覆盖 规则引擎完全开放
包体积 ~10KB 引擎 ~6KB + 按需
自定义规则 仅通过 theme.extend 正则 + 函数,任意自定义
变体系统 固定集合 任意自定义变体函数
属性化模式 需要 plugin 内置预设
图标支持 需单独方案 内置 presetIcons
引擎速度 很快 极快
模式 框架 引擎

核心差异在于理念不同:Tailwind 是一个框架,预设了一套完整的样式系统;而 UnoCSS 是一个引擎,只负责匹配和生成。


七、在 Vite / Nuxt 中配置

// vite.config.ts
import UnoCSS from 'unocss/vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({ plugins: [UnoCSS(), vue()] })
// uno.config.ts
import { defineConfig, presetWind, presetAttributify, presetIcons, transformerDirectives, transformerVariantGroup } from 'unocss'

export default defineConfig({
  presets: [presetWind(), presetAttributify(), presetIcons({ scale: 1.2 })],
  transformers: [transformerDirectives(), transformerVariantGroup()],
  shortcuts: {
    'btn': 'px-4 py-2 rounded-lg font-medium transition-colors cursor-pointer',
    'btn-primary': 'btn bg-blue-500 text-white hover:bg-blue-600',
  },
})

八、Transformers(转换器)

transformerDirectives

.btn { @apply px-4 py-2 rounded-lg bg-blue-500 text-white; @apply hover:bg-blue-600 transition-colors; }

transformerVariantGroup

<!-- 分组写法 -->
<div class="hover:(bg-blue-500 text-white border-blue-300)"></div>
<div class="md:(flex items-center justify-between)"></div>

九、性能优化与最佳实践

实践 建议
预设选择 优先用 presetWind + presetAttributify
规则优先级 具体 → 通用,从上到下
Shortcuts 抽取高频组合,保持 DRY
Safelist 动态拼接的类名需要加入 safelist
Blocklist 阻止不需要的规则生成
图标按需 使用 presetIcons 而非图标字体
Variant Groups 开启 transformerVariantGroup 减少重复
CSS Layers 利用 layers 控制优先级

十、完整生产级配置

import { defineConfig, presetWind, presetAttributify, presetIcons, presetTypography, presetWebFonts, transformerDirectives, transformerVariantGroup, presetContainerQueries } from 'unocss'

export default defineConfig({
  presets: [
    presetWind(),
    presetAttributify(),
    presetIcons({ scale: 1.2, prefix: 'i-', extraProperties: { display: 'inline-block', 'vertical-align': 'middle' } }),
    presetTypography(),
    presetWebFonts({ provider: 'google', fonts: { sans: ['Inter:400,600,700'], mono: ['Fira Code:400,600'] } }),
    presetContainerQueries(),
  ],
  transformers: [transformerDirectives(), transformerVariantGroup()],
  theme: {
    colors: { brand: { 50: '#eff6ff', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8' } },
  },
  shortcuts: {
    'btn': 'inline-flex items-center justify-center px-4 py-2 rounded-lg font-medium transition-all duration-200 cursor-pointer',
    'btn-primary': 'btn bg-brand-500 text-white hover:bg-brand-600 active:scale-95',
    'card': 'bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 p-6',
    'input': 'w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-brand-500 outline-none transition-all',
  },
  rules: [
    [/^animate-(\w+)$/, ([, name]) => ({ animation: `${name} 1s ease-in-out infinite` })],
    ['scrollbar-thin', { 'scrollbar-width': 'thin', 'scrollbar-color': 'rgb(203 213 225) transparent' }],
  ],
  safelist: ['animate-fade-in', 'animate-slide-up'],
})

结语

UnoCSS 的核心理念——引擎而非框架——赋予了前端开发者前所未有的灵活性。通过规则系统、变体系统、预设生态和转换器的组合,你可以构建出完全符合项目需求的原子化 CSS 体系。

相比于 Tailwind,UnoCSS 在扩展性、性能和开发体验上都有显著优势。在实际项目中,建议从 presetWind 起步,逐步引入 presetAttributify、presetIcons 等预设,通过 shortcuts 和自定义规则构建属于自己的设计系统。

Comments | 0条评论