Appearance
UnoCSS
简介
UnoCSS是一个即时的原子化CSS引擎,由Vite团队成员Anthony Fu创建。它被设计为极其可定制和灵活的CSS引擎,具有高性能、零配置和丰富的预设功能。UnoCSS本身不是一个框架,而是一个引擎,它不包含任何预定义的实用工具类,所有功能都通过预设和规则提供。
核心特性
即时生成(On-demand)
UnoCSS只生成你实际使用的CSS,无需清除未使用的样式:
html
<!-- 只有这些类会被生成 -->
<div class="text-center font-bold text-2xl text-red-500">
Hello UnoCSS
</div>原子化CSS
与Tailwind CSS类似,UnoCSS提供了原子化的CSS类,但具有更灵活的命名约定:
html
<!-- 基本样式 -->
<div class="m-4 p-2 text-red-500 bg-gray-100 rounded-lg">
基本样式
</div>
<!-- 响应式设计 -->
<div class="text-center sm:text-left md:text-right lg:text-justify">
响应式文本对齐
</div>
<!-- 状态变体 -->
<button class="bg-blue-500 hover:bg-blue-700 active:bg-blue-800">
交互按钮
</button>属性化模式
UnoCSS的属性化模式允许你使用HTML属性而不是类来应用样式:
html
<!-- 使用类 -->
<div class="text-red-500 p-4 border-2 border-blue-500">
使用类的样式
</div>
<!-- 使用属性 -->
<div text="red-500" p="4" border="2 blue-500">
使用属性的样式
</div>纯CSS图标
UnoCSS提供了将图标作为纯CSS样式的能力,支持多种流行的图标集:
html
<!-- 使用图标 -->
<div class="i-carbon-home text-2xl"></div>
<div class="i-mdi-account text-3xl text-blue-500"></div>
<div class="i-logos-vue text-4xl"></div>安装与配置
基本安装
bash
# 使用npm
npm install -D unocss
# 使用yarn
yarn add -D unocss
# 使用pnpm
pnpm add -D unocssVite集成
javascript
// vite.config.js
import { defineConfig } from 'vite'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
UnoCSS(),
],
})基本配置
javascript
// uno.config.js
import { defineConfig, presetUno, presetAttributify, presetIcons } from 'unocss'
export default defineConfig({
presets: [
presetUno(), // 默认预设,类似Tailwind/Windi CSS
presetAttributify(), // 启用属性化模式
presetIcons(), // 启用图标支持
],
rules: [
// 自定义规则
['custom-rule', { color: 'red' }],
[/^custom-(.+)$/, ([, name]) => ({ color: name })],
],
shortcuts: {
// 快捷方式
'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
'btn-green': 'btn text-white bg-green-500 hover:bg-green-700',
},
theme: {
colors: {
'brand': '#1C1C1C',
},
},
})在项目中引入
javascript
// main.js
import 'uno.css' // 导入生成的CSS预设系统
UnoCSS的预设系统是其最强大的特性之一,允许你轻松扩展或定制功能:
官方预设
javascript
import { defineConfig } from 'unocss'
import {
presetUno, // 默认预设,类似Tailwind/Windi CSS
presetAttributify, // 属性化模式
presetIcons, // 图标支持
presetTypography, // 排版预设
presetWebFonts, // Web字体预设
presetTagify, // 标签化模式
presetMini, // 最小预设
} from 'unocss'
export default defineConfig({
presets: [
presetUno(),
presetAttributify(),
presetIcons({
scale: 1.2,
collections: {
carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default),
mdi: () => import('@iconify-json/mdi/icons.json').then(i => i.default),
},
}),
presetTypography(),
presetWebFonts({
fonts: {
sans: 'Inter',
mono: 'Fira Code',
},
}),
],
})社区预设
javascript
import { defineConfig } from 'unocss'
import presetUno from '@unocss/preset-uno'
import presetRemToPx from '@unocss/preset-rem-to-px'
import presetScrollbar from 'unocss-preset-scrollbar'
export default defineConfig({
presets: [
presetUno(),
presetRemToPx(), // 将rem单位转换为px
presetScrollbar(), // 自定义滚动条样式
],
})自定义规则与快捷方式
自定义规则
javascript
// uno.config.js
import { defineConfig } from 'unocss'
export default defineConfig({
rules: [
// 静态规则
['flex-center', { display: 'flex', 'align-items': 'center', 'justify-content': 'center' }],
// 动态规则
[/^text-(.+)$/, ([, c]) => ({ color: c })],
// 复杂动态规则
[/^grid-cols-(.+)$/, ([, cols]) => {
if (/^\d+$/.test(cols)) {
return { 'grid-template-columns': `repeat(${cols}, minmax(0, 1fr))` }
}
return { 'grid-template-columns': cols }
}],
// 使用函数匹配器
[/^size-(\d+)$/, ([, size]) => ({ width: `${size}px`, height: `${size}px` })],
],
})快捷方式
javascript
// uno.config.js
import { defineConfig } from 'unocss'
export default defineConfig({
shortcuts: {
// 静态快捷方式
'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',
'btn-green': 'btn text-white bg-green-500 hover:bg-green-700',
// 动态快捷方式
'btn-': c => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`,
// 复杂动态快捷方式
'card': 'bg-white rounded-lg shadow-md p-4 m-2',
'card-hover': 'card transform transition-transform hover:scale-105',
},
})高级功能
变体组
html
<!-- 变体组允许你将多个变体应用到一组类 -->
<div class="hover:(bg-gray-400 font-medium) dark:(bg-dark-800 text-white)">
变体组示例
</div>指令
css
/* uno.css */
@unocss-apply;
/* 使用@apply指令 */
.custom-component {
@apply text-center font-bold text-lg text-blue-500;
}属性化模式的高级用法
html
<!-- 基本属性 -->
<div text="sm blue-500" bg="gray-100" p="x-4 y-2" m="t-2 b-4">
属性化模式
</div>
<!-- 响应式属性 -->
<div text="sm md:base lg:lg blue-500 dark:blue-300">
响应式文本
</div>
<!-- 属性变体组 -->
<div hover="(bg-gray-100 text-blue-500)">
悬停效果
</div>纯CSS图标的高级用法
html
<!-- 基本图标 -->
<div class="i-carbon-home"></div>
<!-- 调整图标大小和颜色 -->
<div class="i-carbon-home text-2xl text-blue-500"></div>
<!-- 响应式图标 -->
<div class="i-carbon-home sm:i-carbon-user md:i-carbon-settings"></div>
<!-- 图标变体 -->
<div class="i-carbon-home dark:i-carbon-moon"></div>与框架集成
Vue集成
javascript
// vite.config.js
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
Vue(),
UnoCSS(),
],
})vue
<!-- App.vue -->
<template>
<div class="flex min-h-screen items-center justify-center bg-gray-100">
<div class="p-8 bg-white rounded-xl shadow-md">
<h1 class="text-2xl font-bold text-blue-500 mb-4">
UnoCSS with Vue
</h1>
<p class="text-gray-600">
使用UnoCSS构建Vue应用
</p>
<button class="mt-4 btn-green">
开始使用
</button>
</div>
</div>
</template>React集成
javascript
// vite.config.js
import { defineConfig } from 'vite'
import React from '@vitejs/plugin-react'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
React(),
UnoCSS(),
],
})jsx
// App.jsx
import React from 'react'
import 'uno.css'
function App() {
return (
<div className="flex min-h-screen items-center justify-center bg-gray-100">
<div className="p-8 bg-white rounded-xl shadow-md">
<h1 className="text-2xl font-bold text-blue-500 mb-4">
UnoCSS with React
</h1>
<p className="text-gray-600">
使用UnoCSS构建React应用
</p>
<button className="mt-4 btn-green">
开始使用
</button>
</div>
</div>
)
}
export default AppNuxt集成
bash
# 安装Nuxt模块
npm install -D @unocss/nuxtjavascript
// nuxt.config.js
export default defineNuxtConfig({
modules: [
'@unocss/nuxt',
],
unocss: {
// UnoCSS配置
},
})性能优化
开发模式优化
- UnoCSS默认使用即时生成模式,只生成使用的CSS
- 使用热模块替换(HMR)实现快速更新
- 支持IDE扩展,提供自动完成和预览功能
生产模式优化
javascript
// vite.config.js
import { defineConfig } from 'vite'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
UnoCSS({
// 生产模式优化
minify: true,
// 提取CSS到单独文件
extractCSS: true,
}),
],
})与其他CSS框架对比
| 特性 | UnoCSS | Tailwind CSS | Windi CSS | Vanilla CSS |
|---|---|---|---|---|
| 性能 | 极快 | 快(JIT模式) | 快 | 取决于项目 |
| 灵活性 | 极高 | 高 | 高 | 完全自由 |
| 配置复杂度 | 低 | 中 | 中 | 无 |
| 自定义能力 | 极强 | 强 | 强 | 完全自由 |
| 预设系统 | 丰富 | 有限 | 有限 | 无 |
| 属性化模式 | 内置 | 需插件 | 内置 | 无 |
| 图标支持 | 内置(纯CSS) | 需插件 | 需插件 | 需手动实现 |
| 文件大小 | 极小 | 小(优化后) | 小 | 取决于项目 |
| 社区生态 | 成长中 | 成熟 | 中等 | 成熟 |
最佳实践
项目组织
- 使用预设系统组织功能
- 使用快捷方式减少重复的类组合
- 考虑使用属性化模式提高可读性
javascript
// uno.config.js
import { defineConfig } from 'unocss'
export default defineConfig({
shortcuts: [
// 布局组件
['layout', 'w-full max-w-7xl mx-auto px-4'],
['card', 'bg-white rounded-lg shadow-md p-4'],
// 按钮组件
['btn', 'px-4 py-2 rounded-lg transition-colors duration-200'],
['btn-primary', 'btn bg-blue-500 text-white hover:bg-blue-600'],
['btn-secondary', 'btn bg-gray-200 text-gray-800 hover:bg-gray-300'],
],
})响应式设计
html
<!-- 移动优先设计 -->
<div class="
grid grid-cols-1 gap-4
sm:grid-cols-2
md:grid-cols-3
lg:grid-cols-4
xl:grid-cols-5
">
<!-- 内容 -->
</div>
<!-- 使用属性化模式 -->
<div
grid="~ cols-1 sm:cols-2 md:cols-3 lg:cols-4 xl:cols-5 gap-4"
>
<!-- 内容 -->
</div>主题切换
html
<!-- 使用暗色模式 -->
<div class="bg-white text-gray-800 dark:bg-gray-800 dark:text-white">
支持暗色模式的内容
</div>
<!-- 自定义主题变体 -->
<div class="bg-white text-gray-800 dark:bg-gray-800 dark:text-white red-theme:(bg-red-50 text-red-900)">
支持多主题的内容
</div>常见问题与解决方案
类名冲突
javascript
// uno.config.js
import { defineConfig } from 'unocss'
export default defineConfig({
// 添加前缀避免冲突
prefix: 'un-',
// 或使用属性化模式
presets: [
presetAttributify({ prefix: 'un-' }),
],
})条件样式
jsx
// React中的条件样式
function Button({ primary }) {
return (
<button
className={`btn ${primary ? 'btn-primary' : 'btn-secondary'}`}
>
按钮
</button>
)
}
// 使用库如clsx
import clsx from 'clsx'
function Button({ primary, disabled }) {
return (
<button
className={clsx(
'btn',
{
'btn-primary': primary && !disabled,
'btn-secondary': !primary && !disabled,
'opacity-50 cursor-not-allowed': disabled
}
)}
>
按钮
</button>
)
}IDE支持
- VS Code: UnoCSS VS Code Extension
- WebStorm: 支持通过CSS类名自动完成