大家好,我是前端架构师,关注微信公众号【程序员大卫】免费领取前端精品资料。
背景
今天,我们来聊聊 Unocss,这是一款高性能的原子化 CSS 引擎。通过它,你可以在开发中写出更简洁、更高效的 CSS 代码。
接下来,我将结合自己线上项目的实战经验,举一些具体例子,帮助你更直观地理解 Unocss 的强大功能。
Demo 地址:codesandbox.io/p/devbox/lt…
完整源码在文末获取 👇
直观体验:Unocss 的魔力
看看下面这两张图,感受一下使用 Unocss 编写 CSS 的魔法。
什么是 Unocss?
Unocss 是高性能原子化 CSS 引擎,通过以下特性彻底改变你的 CSS 开发体验:
- 🚀 按需生成:只用到的样式才会打包
- 🎨 智能提示:IDE 自动补全类名
- 🧩 灵活扩展:轻松创建自定义规则
- 📱 响应式支持:内置媒体查询方案
实现需求
假设你有一个 1920 x 1080 的页面,HTML 如下:
<div class="w-400 h-400 b-10_solid_red text-50 flex-center">Hello World</div>
你希望最终输出的样式如下,那么如何实现这个需求呢?
width: 400px;
height: 400px;
border: 10px solid red;
font-size: 50px;
display: flex;
align-items: center;
justify-content: center;
Unocss 集成到 Vite 项目
1. 初始化 Vue 项目
首先,创建一个新的 Vue 项目:
pnpm create vite use-unocss --template vue-ts
2. 安装依赖包
安装 Unocss 以及其他可以帮助你进行单位转换的插件:
pnpm i unocss @unocss/preset-rem-to-px postcss-pxtorem @types/postcss-pxtorem -D
我们使用
@unocss/preset-rem-to-px来将rem转换为px,同时用postcss-pxtorem让px转换为rem,方便你更灵活地编写样式。最终,像w-100这样的类名会自动转换为{ width: 100px }。
3. 配置 Vite
打开 vite.config.ts,并添加 UnoCSS 插件:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import UnoCSS from "unocss/vite";
export default defineConfig({
plugins: [vue(), UnoCSS()],
});
4. 导入uno.css 和 配置页面自适应
在 main.ts 中,添加以下代码,使页面能根据窗口大小自动调整字体大小,并导入 uno.css。
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import "uno.css"; // 导入 uno.css
const setRemUnit = () => {
const docEl = document.documentElement;
const pageWidth = docEl.clientWidth;
docEl.style.fontSize = pageWidth / 10 + "px";
};
setRemUnit();
window.addEventListener("resize", setRemUnit);
createApp(App).mount("#app");
5. 配置 Unocss
创建一个 uno.config.ts 文件,配置一些基础选项,具体每项的详细配置将在后面介绍。
import { defineConfig } from 'unocss'
export default defineConfig({
variants: [],
shortcuts: {},
rules: [],
presets: [],
transformers: []
});
6. 配置 PostCSS
最后,创建一个 postcss.config.js 文件,配置 px 转 rem:
export default {
plugins: {
"postcss-pxtorem": {
rootValue: 192, // 假设设计稿宽度为 1920px
propList: ["*"],
minPixelValue: 2, // 忽略小于 2px 的转换
},
},
};
Unocss 配置详解
1. variants
variants 用于配置样式的变体,对在不同分辨率的自适应布局非常有用!
例如,以下配置定义了一个媒体查询,只有在宽高比为 24/9 时才会生效。如果我们使用 5k:w-200,它仅会在宽高比为 24/9 时,将元素的宽度设置为 200px。
{
variants: [
(matcher) => {
if (matcher.startsWith("5k:")) {
return {
matcher: matcher.slice(3),
parent: "@media (aspect-ratio: 24/9)",
};
}
},
],
}
2. shortcuts
shortcuts 用于定义常用的样式组合。例如,定义一个 flex-center,它包含了 flex、justify-center 和 items-center,而这些类名又因 Unocss 的预设分别代表不同的含义,如下:
flex代表display: flex。justify-center代表justify-content: center。items-center代表align-items: center。
这些组合可以显著的提高开发效率:
{
shortcuts: {
"flex-center": "flex justify-center items-center",
"flex-x-center": "flex justify-center",
"flex-y-center": "flex items-center",
"flex-x-between": "flex items-center justify-between",
"flex-x-end": "flex items-center justify-end",
"wh-full": "w-full h-full",
"text-truncate": "whitespace-nowrap overflow-hidden text-ellipsis",
"bg-no-repeat-contain": "bg-no-repeat bg-contain",
"bg-no-repeat-cover": "bg-no-repeat bg-cover",
"abs-full": "absolute left-0 right-0 top-0 bottom-0",
"abs-x-center": "absolute left-50% top-0 translate-x--1/2",
"abs-y-center": "absolute left-0 top-50% translate-y--1/2",
"abs-center": "absolute left-50% top-50% translate-x--1/2 translate-y--1/2",
},
}
3. presets
presets 是 Unocss 的一种配置机制,提供了一些常用的预设配置。
-
presetRemToPx({ baseFontSize: 4 }): 这个预设将所有的rem单位转换为px,并使用基础字体大小(baseFontSize)进行转换。例如,baseFontSize为4时,1rem转换为4px,2rem转换为8px。 -
presetUno(): 默认预设,提供了常用工具类(如背景色、间距、排版等),并动态生成 CSS。
import { defineConfig, presetUno } from "unocss";
import presetRemToPx from "@unocss/preset-rem-to-px";
export default defineConfig({
presets: [
presetRemToPx({ baseFontSize: 4 }),
presetUno(),
],
})
4. transformers
transformers 用于扩展和转换输入的类名。
-
transformerDirectives(): 处理指令类(如@apply、@screen、@variants),并将其转化为实际的 CSS 规则或媒体查询。 -
transformerVariantGroup(): 处理变体类的组合(如hover:bg-red-500、focus:text-white),并将它们合并为一组 CSS 声明,使类名更加简洁。
import { defineConfig, transformerDirectives, transformerVariantGroup } from "unocss";
import presetRemToPx from "@unocss/preset-rem-to-px";
export default defineConfig({
transformers: [transformerDirectives(), transformerVariantGroup()],
})
5. rules
rules 用于定义自定义的 CSS 规则,并支持正则匹配。通过这些规则,你可以创建简洁而强大的 CSS 语法,提高开发效率:
1. transform 相关
transform-1-linear相当于{ transition: transform 1s linear; }transform-2-bounce相当于{ transition: transform 2s bounce; }
[
/^transform-(\d+)-(.+)$/,
([, duration, timingFunction]) => ({
transition: `transform ${duration}s ${timingFunction}`,
}),
]
2. width 和 height 联合简写
wh-10相当于{ width: 10px; height: 10px; }
[
/^wh-(\d+)$/,
([, wh]) => ({
width: `${wh}px`,
height: `${wh}px`,
}),
]
3. absolute 相关简写
absolute-l-10相当于{ position: absolute; left: 10px; }absolute-lr-10相当于{ position: absolute; left: 10px; right: 10px; }
[
/^absolute-([lrtb]{1,4})-(\d+)$/,
([, directions, dis]) => {
const styles = {
position: "absolute",
};
const obj = {
l: "left",
r: "right",
t: "top",
b: "bottom",
};
for (const key in obj) {
if (directions.includes(key)) {
styles[obj[key]] = dis + "px";
}
}
return styles;
},
]
4. background-color 相关
bg-rgba(255,255,0,0.2)相当于{ background-color: rgba(255,255,0,0.2); }
[
/^bg-rgba\((\d+),(\d+),(\d+),([0,1]?\.?\d*)\)$/,
([, r, g, b, a]) => ({
"background-color": `rgba(${r},${g},${b},${a})`,
}),
]
5. border 相关
b-1_solid_blue相当于{ border: 1px solid blue; }bt-1_solid_red相当于{ border-top: 1px solid red; }br-1_dashed_rgba(255,0,0,0.5)相当于{ border-right: 1px dashed rgba(255,0,0,0.5); }
注意:目前 VSCode 插件 Unocss 不支持预览带有
rgba的写法。
[
/^(b|outline)(t|r|b|l)?-(\d+)_(solid|dashed|dotted)_(#[0-9a-fA-F]{3,6}|rgba\((\d+),(\d+),(\d+),([0,1]?\.?\d*)\)|\w+)$/,
([, type, dir = "", width, style, color]) => {
const bType = {
b: "border",
outline: "outline",
};
const dirObj = {
t: "-top",
r: "-right",
b: "-bottom",
l: "-left",
"": "",
};
return {
[`${bType[type]}${dirObj[dir]}`]: `${width}px ${style} ${color}`,
};
},
]
6. background 相关
bg[url]相当于{ background: url(xxx) no-repeat left top / contain; }bg-cover[url]相当于{ background: url(xxx) no-repeat left top / cover; }bg-center_top[url]相当于{ background: url(xxx) no-repeat center top / cover; }bg-left_center-100%_120%[url]相当于{ background: url(xxx) no-repeat left center / 100% 120%; }
[
/^bg(?:-([a-z]+-[a-z]+|repeat))?(?:-(\d+%?_\d+%?|[a-z]+_[a-z]+))?(?:-(\d+%?_\d+%?|[a-z]+))?\[(.*)\]$/,
([, repeat = "no-repeat", pos = "left_top", size = "contain", url]) => {
return {
background: `url(${url}) ${repeat} ${pos.replace(
"_",
" "
)} / ${size.replace("_", " ")}`,
};
},
]
7. padding 和 margin
p-1相当于{ padding: 1px; }p-1_2相当于{ padding: 1px 2px; }p-1_2_3相当于{ padding: 1px 2px 3px; }p-1_2_3_4相当于{ padding: 1px 2px 3px 4px; }m-1相当于{ margin: 1px; }m-1_2相当于{ margin: 1px 2px; }m-1_2_3相当于{ margin: 1px 2px 3px; }m-1_2_3_4相当于{ margin: 1px 2px 3px 4px; }
[
/^([pm])-(\d+)(?:_(\d+))(?:_(\d+))?(?:_(\d+))?(?:_(\d+))?$/,
([, type, top, right, bottom, left]) => {
const pm = type === "p" ? "padding" : "margin";
const sides = [top, right, bottom, left]
.filter(Boolean)
.map((item) => item + "px")
.join(" ");
return {
[pm]: sides,
};
},
]
总结
通过本文的配置方案,你可以:
✅ 减少 70% 的 CSS 代码量
✅ 提升 3 倍样式开发速度
✅ 轻松实现响应式布局
✅ 告别 class 命名焦虑
Tips:建议配合 VSCode 的Unocss 插件使用,获得代码提示和实时预览功能。
Unocss 插件地址:
完整源码地址:
如果本文对你有帮助,欢迎点赞❤️收藏⭐,也欢迎在评论区交流您的 Unocss 使用心得!