UnoCSS正则规则仅匹配HTML中静态class字符串字面量,不处理JS表达式或模板插值;需加^$锚点、捕获组与回调参数严格对齐,并通过theme解构或safeList支持动态值。

正则规则必须匹配 class 字符串字面量
UnoCSS 的 rules 里写的正则,只作用于 HTML 或模板中实际出现的 class 属性值——而且是静态字符串。它不会执行 JS、不解析 Vue 插值、不运行表达式。比如 class="m-4" 能被 /^m-(\d+)$/ 捕获;但 class={"m-" + size} 或 class="m-{{size}}" 完全无效。
常见错误现象:
- 写了正则规则,但对应样式没生成,
unocss --inspect里也看不到该类名 - 页面上用了
m-8,但最终 CSS 里只有m-4和m-12 - 正则写成了
/m-(\d+)/(缺少锚点),结果把text-m-8也误匹配了
正则捕获组必须与回调参数严格对齐
UnoCSS 要求正则的捕获组数量和回调函数参数数量一致,且第一个参数始终是完整匹配字符串(通常用 [, d] 忽略)。错位会导致 undefined 或运行时错误。
正确写法示例:
立即学习“前端免费学习笔记(深入)”;
[/^m-(\d+)$/, ([, d]) => ({ margin: `${d}px` })] // ✅ 一个捕获组 → 两个参数
[/^p-(\d+)-(\w+)$/, ([, d, unit]) => ({ padding: `${d}${unit}` })] // ✅ 两个捕获组 → 三个参数
[/^text-(\d+)(rpx|rem)$/, ([, size, unit]) => ({
fontSize: unit === 'rpx' ? `${size}rpx` : `${size}rem`
})]
容易踩的坑:
- 写成
(\d+)却在回调里写([, d, unit])→unit是undefined - 用了非捕获组
(?:...)却误以为它会进参数列表 - 正则末尾漏了
$,导致m-100px被截成m-10(只匹配前两位)
动态规则要配合 theme 或 safeList 才能支持变量引用
正则规则本身不能直接读取 theme.spacing 或 theme.colors,除非你在回调里显式传入或解构 theme。但 UnoCSS 的 rules 回调默认不接收 theme 参数——它只在 shortcuts 函数签名里原生支持。
两种可行路径:
- 在
rules回调中手动引用theme:需把theme提前从配置中解构出来,再闭包进 rule 数组(注意 Vite 热更新可能不触发重解析) - 改用
shortcuts+ 函数形式:例如btn-primary: ({ theme }) => `bg-${theme.colors.primary}-500 text-white` - 对无法静态分析的动态值(如用户输入的尺寸),加进
safeList:例如safeList: ['m-${n}', 'w-[${w}px]'],但会失去原子化按需优势
复杂正则建议先本地验证再集成
正则写错不会报构建错误,只会静默失效。最可靠的方式是脱离构建流程,用 Node.js 小脚本快速验证匹配逻辑:
const re = /^text-(\d+)(rpx|rem)$/
console.log(re.exec('text-16rpx')) // → ['text-16rpx', '16', 'rpx']
console.log(re.exec('text-16px')) // → null
真正卡住人的往往不是正则语法本身,而是 extractor 和代码写法之间的“信任边界”——它只认字符串字面量,不理解任何运行时逻辑。想让 m-${size} 生效,要么改成 attributify 模式(m={size}),要么老老实实列进 safeList。


















