unocss 默认不生成 hover 类是因为启用「按需提取」,静态分析无法捕获字符串拼接或动态绑定中的伪类变体;需在 uno.config.ts 中显式配置 variants: ['hover'] 或使用 preset-mini 并确认变体启用。

UnoCSS 为什么默认不生成 hover 类?
因为 UnoCSS 默认启用「按需提取」,只扫描源码中真实出现的原子类,而 hover:underline 这类伪类变体不会被静态分析捕获——它藏在字符串拼接、动态 class 绑定或模板语法里,工具看不到。
常见错误现象:hover:bg-blue-500 写了但没生效,检查 DevTools 发现对应 CSS 根本没生成。
- 解决方法:在
uno.config.ts中显式启用hover变体支持:import { defineConfig } from 'unocss'<br>export default defineConfig({<br> theme: {<br> variants: ['hover', 'focus', 'active']<br> }<br>) - 更稳妥的做法是配合
@unocss/preset-mini(它已内置常用变体),但注意:仅引入 preset 不等于自动开启所有变体,仍需确认配置中variants字段是否包含你需要的 - Vue / React 中用
className={isHovered ? 'hover:underline' : ''}这种写法,UnoCSS 依然无法提取——得改用class="hover:underline"静态写死,或启用attributifyPreset+data-uno属性方式
开发时样式丢失,但 build 后正常?
这是 UnoCSS 的「开发时热更新机制」和「构建时完整扫描」行为差异导致的。开发服务器(如 Vite)依赖插件监听文件变化并增量生成 CSS;若改动未触发重扫描(比如只改了 JS 逻辑但 class 字符串是拼出来的),旧 CSS 就不会更新。
使用场景:你在 Vue 的 setup() 里用 computed(() => `text-${color}-500`) 动态生成 class,开发时改 color 值,UnoCSS 不会重新提取新组合。
立即学习“前端免费学习笔记(深入)”;
- 临时解决:保存任意一个 .vue 或 .ts 文件强制触发 UnoCSS 全量重扫
- 长期规避:避免运行时拼接原子类名;改用
style对象绑定,或把可能的取值枚举写死在模板里(如v-for="c in ['red', 'blue']" :key="c")让提取器看见 - 性能影响:启用
content.passthrough模式可强制扫描所有字符串,但会显著拖慢 HMR,仅调试时开
defineShortcuts 和 theme.extend.colors 哪个更适合自定义色板?
直接用 theme.extend.colors。快捷方式(defineShortcuts)本质是 class 别名,不产生新颜色 token,无法参与 bg- / text- 等前缀的自动推导;而扩展主题色后,bg-mycolor-500、text-mycolor-200 全部自动可用。
参数差异:defineShortcuts 接收数组,每项是 ['my-btn', 'px-4 py-2 bg-blue-500 rounded'] 这样的映射;theme.extend.colors 是对象,如 { mycolor: { 50: '#f0f9ff', 500: '#0ea5e9' }。
- 如果你只需要一组固定 class 组合(比如按钮样式),
defineShortcuts更轻量 - 但只要涉及颜色、间距、字体等需要被多个前缀复用的值,必须走
theme.extend - 容易踩的坑:在
defineShortcuts里写['primary-btn', 'bg-primary-500'],结果primary没在 theme 里定义 → 构建报错Cannot resolve color primary
Vite 插件顺序导致 UnoCSS 不生效?
是的,UnoCSS 必须在其他 CSS 处理插件(尤其是 @vitejs/plugin-vue 和 vite-plugin-pages)之后执行,否则它看不到组件模板里的 class 字符串。
错误配置示例(UnoCSS 插件放太前):
export default defineConfig({<br> plugins: [<br> unocss(), // ❌ 错!此时 Vue 插件还没解析 template<br> vue(),<br> ]<br>})
- 正确顺序:UnoCSS 插件必须排在
vue()、react()、solid()等框架插件之后 - 如果用了
vite-plugin-inspect,UnoCSS 也得放在它前面,否则 inspect 面板看不到提取结果 - 兼容性影响:某些老版本 Vite(
最常被忽略的一点:UnoCSS 的 content 配置里写的 glob 路径,必须覆盖到你实际写 class 的所有文件类型。比如用了 Markdown 写文档,却只配了 **/*.vue,那 class="text-sm" 在 .md 里就永远不会被提取。










