Appearance
UnoCss
安装与配置
bash
npm install -D unocss
Vite.config.ts
ts
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [UnoCSS()]
})
main.ts
ts
import 'virtual:uno.css'
uno.config.ts
ts
import {
defineConfig,
presetAttributify,
presetIcons,
presetTypography,
presetWebFonts,
presetWind4,
transformerDirectives,
transformerVariantGroup
} from 'unocss'
import { createRemToPxProcessor } from '@unocss/preset-wind4/utils'
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'
import fs from 'fs'
// 本地SVG图标目录
const iconsDir = './src/assets/icons'
// 读取本地 SVG 目录,自动生成 safelist
const generateSafeList = () => {
try {
return fs
.readdirSync(iconsDir)
.filter(file => file.endsWith('.svg'))
.map(file => `i-svg:${file.replace('.svg', '')}`)
} catch (error) {
console.error('无法读取图标目录:', error)
return []
}
}
// unocss 提供了一些默认的 css 变量,如:--spacing: 0.25rem 详细可查看 https://unocss.nodejs.cn/presets/wind4#presetremtopx
export default defineConfig({
// 自定义类名规则,UnoCSS 是按需的,在代码中使用如下自定义类名之前它不会起作用
rules: [
// 规则:m-数字 => margin: 数字px
[/^m-([\.\d]+)$/, ([_, num]) => ({ margin: `${num}px` })],
// 使用:<div h100 w100 bg="img-[@/assets/png/cat.png]" ></div>
[
/^bg-img-\[(.+)\]$/,
([, value]) => {
const path = value.replace(/_/g, '/')
return {
'background-image': `url(${path})`,
'background-repeat': 'no-repeat',
'background-size': '100% 100%'
}
}
]
],
// 自定义快捷类
shortcuts: {
'wh-full': 'w-full h-full',
'flex-center': 'flex justify-center items-center',
'flex-x-center': 'flex justify-center',
'flex-y-center': 'flex items-center',
'flex-x-start': 'flex items-center justify-start',
'flex-x-between': 'flex items-center justify-between',
'flex-x-end': 'flex items-center justify-end'
},
// 自定义主题颜色等配置
theme: {
// 自定义动画
animation: {
keyframes: {
// 使用:<div h312 w300 active:animate-rotate-scale></div>
'rotate-scale': `{
0% { transform: rotate(0deg) scale(1) }
50% { transform: rotate(180deg) scale(1.2) }
100% { transform: rotate(360deg) scale(1) }
}`
}
},
// 自定义颜色变量,将 CSS 变量映射到 Unocss 颜色系统
colors: {
primary: 'var(--el-color-primary)',
primary_dark: 'var(--el-color-primary-light-5)'
},
/**
* 自定义响应式断点
* Object.fromEntries()将其转换为:
{
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px',
'3xl': '1920px',
'4xl': '2560px'
}
实际应用场景
<div class="grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4">
<!-- 在 768px+ 显示2列,1536px+ 显示4列 -->
</div>
最终生成的 CSS:
@media (min-width: 768px) { .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr))}}
@media (min-width: 1536px) { .2xl\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr))}}
*/
breakpoints: Object.fromEntries(
[640, 768, 1024, 1280, 1536, 1920, 2560].map((size, index) => [
['sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'][index],
`${size}px`
])
)
},
// 动态图标
safelist: generateSafeList(),
// 是一组预定义的 Unocss 规则,用于快速集成常用功能
presets: [
// 提供 Tailwind CSS 风格的实用工具类(如 m-4, flex, bg-blue-500),是 Unocss 的核心基础规则集
// 对比 presetWind3,presetWind4 提供了更丰富的功能和更好的性能。
presetWind4({
preflights: {
// presetWind4 内部集成,无需安装任何额外的 CSS 重置包,默认重置样式(重置一些自带样式的标签如:h1 a 等)
// reset: true,
theme: {
// presetWind4 内部提供了 rem 转 px 的转换器,默认为 16.假设这里设置为 4 ,页面上有个元素:<div w100 h30></div>
// 那么该元素的宽度将被转换为 4 * 0.25 * 100 = 100px,高度为 4 * 0.25 * 30 = 30px。
process: createRemToPxProcessor(4)
}
}
}),
// presetRemToPx({ baseFontSize: 1 }) as any,
// 允许使用属性类名即无需通过声明 class="" 也可书写样式,如:<div m-2 text-red>...</div>
presetAttributify(),
// 提供 图标支持,可通过类名直接使用图标(需配合图标库如 @iconify/json)
presetIcons({
// 额外属性
extraProperties: {
display: 'inline-block',
width: '1em',
height: '1em'
},
// 图表集合
collections: {
// svg 是图标集合名称,使用 `i-svg:图标名` 调用
svg: FileSystemIconLoader(iconsDir, svg => {
// 如果 `fill` 没有定义,则添加 `fill="currentColor"`
return svg.includes('fill="')
? svg
: svg.replace(/^<svg /, '<svg fill="currentColor" ')
})
}
}),
// 为富文本内容(如 Markdown 生成的 HTML)提供排版美化
presetTypography(),
// 简化 Web 字体加载(如 Google Fonts)
presetWebFonts()
],
// 转换器在编译阶段动态处理源码,增强语法能力
transformers: [
/**
支持 CSS 指令语法(类似 Sass/Less)
在 CSS 中应用工具类
.btn {
@apply px-4 py-2 rounded; 输出: .btn { padding: 1rem; border-radius: 0.25rem; }
}
响应式指令
@screen md {
.menu { @apply flex; }
}
*/
transformerDirectives(),
/**
启用 分组语法,合并相同前缀的类,减少重复前缀,提升可维护性
<!-- 原始写法 -->
<div class="hover:bg-blue-500 hover:text-white">...</div>
<!-- 分组写法 (更简洁) -->
<div class="hover:(bg-blue-500 text-white)">...</div>
*/
transformerVariantGroup()
]
})
安装 UnoCss 插件可获得最佳的 IDE 体验
使用技巧
动态图标
在某些场景下只在
uno.config.ts
中配置 collections 选项是不够的还需配合 safelist 选项才行,如:
vue
<script setup lang="ts">
const svg = ref('vue')
function updata() {
svg.value = svg.value === 'vue' ? 'vite' : 'vue'
}
</script>
<template>
<div w50 h50 :class="`i-svg:${svg}`" @click="updata"></div>
</template>
这时在 safelist 选项中配置可能用到的动态图标即可实现上述需求。具体配置可查看上方 uno.config.ts
原生样式属性
vue
<!-- 如此设置 rgba 属性是不生效的 -->
<div h100 w100 border="10 solid rgba(227,64,50,0.5)"></div>
<!-- 如果使用原生样式属性需要使用 “[]” 包裹 -->
<div h100 w100 border="10 solid [rgba(227,64,50,0.5)]"></div>
修改子元素样式
css
:root {
--main-bg-color: brown;
}
vue
<!-- 和 less 中类似可使用 “&” 代表自身元素 -->
<!-- class="[&>div]:bg-[--main-bg-color]" 还可写为 class="[&>div]:bg-(#a52a2a) -->
<div class="[&>div]:bg-[--main-bg-color]">
<div w100 h100></div>
</div>
伪类使用
vue
<!-- 使用伪类,如下也可写为 class="hover:bg-red" -->
<div h100 w100 bg-black hover:bg-red></div>
<!-- 移入父元素,子元素变色。注意类名必须是 group -->
<div w100 h100 bg-green class="group">
<div w50 h50 group-hover:bg-red></div>
</div>
在 css 中使用 unocss
vue
<template>
<div class="box"></div>
</template>
<style scoped>
.box {
@apply w100 h100 bg-(#6a5ffe);
/*
@apply w100 h100 bg-(#6a5ffe) 会被转变为:
width: 100rem;
height: 100rem;
background-color: #6a5ffe;
*/
}
</style>
动画
UnoCss 中提供了一些预设动画:
animate-pulse:元素透明度循环变化
animate-bounce-in:元素弹跳式出现
animate-fade-out:透明度逐渐降为 0
ts
// uno.config.ts
export default defineConfig({
...其他配置,
theme: {
// 自定义动画
animation: {
keyframes: {
'rotate-scale': `{
0% { transform: rotate(0deg) scale(1) }
50% { transform: rotate(180deg) scale(1.2) }
100% { transform: rotate(360deg) scale(1) }
}`
}
}
}
})
vue
<!-- 页面中使用预设动画 -->
<div w50 h50 bg-red active:animate-fade-out></div>
<!-- 页面中使用自定义动画 -->
<div h312 w300 active:animate-rotate-scale></div>
搜索预设类
可前往如下地址查询 UnoCss 提供的预设类名
https://unocss.nodejs.cn/interactive/ 提供交互式文档
https://tailwind.nodejs.cn/docs/aspect-ratio tailwind 文档更加简单易懂,更为推荐
Vite 常用配置
vite.config.ts
ts
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// 自动导入vue中hook reactive ref等
import AutoImport from 'unplugin-auto-import/vite'
// 自动导入ui-组件 比如说ant-design-vue element-plus等
import Components from 'unplugin-vue-components/vite'
// ElementPlus
// import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// AntDesignVue
// import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
UnoCSS(),
AutoImport({
// 安装后在组件中不用再导入 ref,reactive 等
imports: ['vue', 'vue-router'],
// 存放的位置
dts: 'src/auto-import.d.ts'
}),
Components({
// 引入组件的,包括自定义组件
// 存放的位置
// 自动引入 ElementPlus 组件
// resolvers: [ElementPlusResolver()],
// 自动引入 AntDesignVue 组件
// resolvers: [AntDesignVueResolver()],
dts: 'src/components.d.ts'
})
],
resolve: {
alias: {
'@': resolve(__dirname, './src')
}
},
build: {
// 是否生成map文件
sourcemap: false,
terserOptions: {
compress: {
// 发布时删除 console
drop_console: true
}
}
},
server: {
host: '0.0.0.0',
proxy: {
'/api': {
target: process.env.VITE_APP_BASE_URL,
changeOrigin: true
// rewrite: path => path.replace(/^\/api/, '')
}
}
}
})
可前往 https://gitee.com/master-dog/vite-uno-css-vue3-ts-template 详细查看