UnoCSS 的 uno:mt-2 不生效,根本原因是未启用 presetAttributify 插件或其 prefix 配置与模板中属性前缀不匹配;该模式非默认开启,必须在 presets 中显式声明并确保前缀一致,否则属性化写法完全不会被解析。

直接说结论:UnoCSS 的属性化模式(presetAttributify)和自定义 CSS 规则(rules)必须在 uno.config.ts 中显式声明并协同配置,否则属性写法不生效、自定义类名无法解析。
为什么 uno:mt-2 不生效?检查 presetAttributify 是否启用且前缀匹配
属性化模式不是默认开启的,它依赖 presetAttributify 插件,并通过 HTML 属性(如 uno:mt-2)触发解析。常见失效原因:
- 没在
presets数组里加presetAttributify()—— 即使写了rules也白搭 - 启用了
prefix(比如prefix: 'u:'),但模板里仍写uno:mt-2,导致匹配失败 - 用了
ignored列表却误把需要处理的属性名加进去了,例如ignored: ['class']会跳过所有带 class 的属性解析
正确配置示例:
import { defineConfig, presetAttributify } from 'unocss'
export default defineConfig({
presets: [
presetAttributify({ prefix: 'uno:' }), // 必须显式传入,且 prefix 要和模板中一致
],
})
rules 静态 vs 动态:别混淆匹配逻辑和返回值类型
rules 是数组,每项要么是静态二元组 ['类名', CSS 对象],要么是动态正则元组 [正则, 回调函数]。两者语法和行为完全不同:
- 静态规则只认完全匹配的字符串,比如
['text-brand', { color: '#3b82f6' }]只响应text-brand,不响应text-brand-500 - 动态规则用正则捕获,回调必须返回对象(不能返回字符串或空值),例如:
[/^m-(\d+)$/, ([, d]) => ({ margin: `${d}px` })] - 正则回调的参数是
match数组,match[0]是全量匹配串,match[1]才是第一个捕获组 —— 写成match[0]就会把整个m-12当数值用,报错或样式错乱 - 多个规则冲突时,后定义的覆盖先定义的,所以把通用规则(如
/^m-/)放前面,特例(如['m-safe', { margin: 'env(safe-area-inset-top)' }])放后面
单位陷阱:rem 默认 ≠ px,presetRemToPx 不是可选而是刚需
UnoCSS 默认所有长度单位(mt-4、w-64)按 rem 解析,而 1rem = 16px 是浏览器默认值。但多数团队开发时习惯直接写像素值,这时必须引入 @unocss/preset-rem-to-px 并配置 baseFontSize:
- 不装这个 preset:你写
mt-4,实际生成margin-top: 4rem→ 64px,远超预期 - 装了但没配
baseFontSize:默认按 1rem = 1px 换算,mt-4→4px,看似对了但和设计稿单位脱节 - 推荐配
baseFontSize: 4:这样mt-4→4px,mt-16→16px,和 Figma/设计系统单位对齐
配置位置必须在 presets 数组内,顺序无关,但得存在:
import presetRemToPx from '@unocss/preset-rem-to-px'
export default defineConfig({
presets: [
presetUno(),
presetRemToPx({ baseFontSize: 4 }),
],
})
调试时最常忽略的点:Vite 插件加载顺序与 HMR 生效范围
UnoCSS 是 Vite 插件,它的解析发生在模块编译阶段。以下问题几乎都源于加载时机或作用域:
- Vite 配置里没加
UnoCSS()插件,或加在vue()之后但模板已提前被解析 —— 必须确保UnoCSS()在vue()前 - 改了
uno.config.ts但页面没刷新出新样式 —— UnoCSS 默认缓存配置,需手动重启 Vite 进程(热更新不触发 config 重载) - 在
.vue文件的<style></style>块里写@apply,但没启用transformerDirectives—— 这个 transformer 需单独 import 并加入transformers配置项 - 使用
shortcuts时写了正则但没加transformerVariantGroup,导致btn-md:hover这类组合失效
真正麻烦的从来不是怎么写规则,而是规则写了却不知道为什么没生效 —— 多数时候卡在插件链、缓存、或单位换算这三步上。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











