中文文档:https://unocss-cn.pages.dev/
一. Unocss基本使用
1. 安装
npm install -D unocss
2. vite.config.ts中安装插件
// vite.config.ts
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
UnoCSS(),
],
})
3. 创建 uno.config.ts 文件:
// uno.config.ts
import { defineConfig } from 'unocss'
export default defineConfig({
// ...UnoCSS options
})
默认情况下,UnoCSS 将自动查找项目根目录中的 uno.config.{js,ts,mjs,mts} 或 unocss.config.{js,ts,mjs,mts}。您也可以手动指定配置文件,例如在 Vite 中:
// vite.config.ts
import { defineConfig } from 'vite'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
UnoCSS({
configFile: '../my-uno.config.ts',
}),
],
})
4. 将 virtual:uno.css 添加到主入口文件:
// main.ts
import 'virtual:uno.css'
5. 基本使用
以上步骤完成后即可在项目中随意使用类名啦,具体类名及样式可在https://unocss-cn.pages.dev/interactive/中搜索。
例:
二. 配置(link)
1. 预设
默认预设:presetUno
// uno.config.ts
import { defineConfig } from 'unocss'
import presetUno from '@unocss/preset-uno'
export default defineConfig({
presets: [
presetUno(),
],
// presets: [], // 禁用默认 preset
})
该预设试图提供一种常见的实用程序优先框架的超集,包括 Tailwind CSS、Windi CSS、Bootstrap、Tachyons 等。
例如,ml-3(Tailwind CSS)、ms-2(Bootstrap)、ma4(Tachyons)和 mt-10px(Windi CSS)都是有效的。
.ma4 { margin: 1rem; }
.ml-3 { margin-left: 0.75rem; }
.ms-2 { margin-inline-start: 0.5rem; }
.mt-10px { margin-top: 10px; }
2. 规则
规则定义了实用类和生成的 CSS。UnoCSS 有许多内置规则,但也允许轻松添加自定义规则。
// uno.config.ts
import { defineConfig } from 'unocss'
import presetUno from '@unocss/preset-uno'
export default defineConfig({
rules: [
// 注意:属性语法遵循 CSS 属性语法,例如 font-weight 而不是 fontWeight。如果属性名中有连字符 -,应该用引号括起来。
['font-bold', { 'font-weight': 700 }],
[/^bd-(\d+)$/, ([, d]) => ({ border: `${d}px solid #ddd` })],
[/^p-(\d+)$/, (match) => ({ padding: `${match[1]}px` })],
// 使用主题
// [
// /^text-(.*)$/,
// ([, c], { theme }) => {
// if (theme.colors[c]) return { color: theme.colors[c] };
// },
// ],
],
})
例如:每当在用户代码中检测到 bd-1 时,将生成以下 CSS:
.bd-1 { border: 1px solid #ddd }
3. 快捷方式
快捷方式允许您将多个规则组合成单个简写。
// uno.config.ts
import { defineConfig } from 'unocss'
import presetUno from '@unocss/preset-uno'
export default defineConfig({
shortcuts: [
{
btn: 'py-2 px-4 font-semibold rounded-lg shadow-md cursor-pointer',
},
// 动态快捷方式
[/^btn-(.*)$/, ([, c]) => `bg-${c} text-#fff hover:bg-${c}/80 py-2 px-4 font-semibold rounded-lg shadow-md cursor-pointer`],
// 使用主题
// [
// /^badge-(.*)$/,
// ([, c], { theme }) => {
// if (theme.colors[c]) return `bg-${c}:10 text-${c} rounded`;
// },
// ],
],
})
例如:每当在用户代码中检测到 btn-blue 时,将生成以下 CSS:
.btn-blue {
cursor: pointer;
border-radius: 0.5rem;
--un-bg-opacity: 1;
background-color: rgb(96 165 250 / var(--un-bg-opacity));
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
--un-text-opacity: 1;
color: rgb(255 255 255 / var(--un-text-opacity));
font-weight: 600;
--un-shadow: var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgb(0 0 0 / 0.1)), var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);
}
.btn-blue:hover {
background-color: rgb(96 165 250 / 0.8);
}
4. 主题
// uno.config.ts
import { defineConfig } from 'unocss'
import presetUno from '@unocss/preset-uno'
export default defineConfig({
theme: {
colors: {
myBg: {
// class="bg-my-bg-1"
1: '#CCFFFF',
2: '#CCFFFF',
3: '#99CCFF',
4: '#3399CC',
},
myText: {
// class="text-my-text-1"
1: '#CCFFFF',
3: '#99CCFF',
2: '#003366',
},
myBorder: {
// class="text-my-border-1"
1: '#003366',
},
},
// 当提供自定义 breakpoints 对象时,默认对象将被覆盖而不是合并。以下示例将只能使用 sm: md: lg:断点变体
// 由于 uno 不支持不同单位大小的比较排序,请转换为相同单位。
// breakpoints: {
// sm: '320px',
// md: `${40 * 16}px`,
// lg: '960px',
// },
})
<div class="bg-my-bg-2 p-40px">
<span class="btn-primary" @click="count++">count is {{ count }}</span>
<h1 class="bg-myBg-4 text-my-text-1">h1 h1 h1 h1 h1 h1 h1 h1 h1 h1 h1 h1</h1>
<h2 class="mybd-my-border-1 text-my-text-2">h2 h2 h2 h2 h2 h2 h2 h2 h2 h2 h2 h2</h2>
<span class="btn-my-bg-4">span 2</span>
</div>
5. 转换器
指令转换器: transformerDirectives, 可以使用 @apply, theme() 在样式文件中更方便的使用自定义的主题色。
// uno.config.ts
import { defineConfig } from 'unocss'
import transformerDirectives from '@unocss/transformer-directives'
export default defineConfig({
transformers: [
transformerDirectives(),
],
})
html {
background-color: theme('colors.myBg.1');
}
.btn-primary {
@apply text-white bg-my-bg-3 cursor-pointer hover:bg-my-bg-3/80;
// --at-apply: 'text-white bg-my-bg-3 hover:bg-my-bg-3'; // css 写法
}
6. 白名单safelist
在使用转化器的 theme('colors.myBg.1'),发现colors.myBg.1没有生成对应的变量,所以样式不生效,但是在html, 或是css 中用到 XX-my-bg-1的类名时,变量则会生成。
由于 UnoCSS 在构建时使用静态提取工作,变量可能提取不到,所以使用safelist做特殊处理:
// uno.config.ts
import { defineConfig } from 'unocss'
import transformerDirectives from '@unocss/transformer-directives'
export default defineConfig({
safelist: ['bg-myBg-1', 'bg-myBg-2'],
})
三. 主题切换
1. 安装
npm i -D unocss-preset-theme
2. 新建theme文件
export const myTheme = {
default: {
colors: {
myBg: {
1: '#eaf7f7',
2: '#CCFFFF',
3: '#99CCFF',
4: '#3399CC',
},
myText: {
1: '#CCFFFF',
3: '#99CCFF',
2: '#003366',
},
myBorder: {
1: '#003366',
},
},
},
red: {
colors: {
myBg: {
1: '#FFCCCC',
2: '#FF9999',
3: '#FF6666',
4: '#FF0033',
},
myText: {
1: '#FFCCCC',
3: '#FF6666',
2: '#FF0033',
},
myBorder: {
1: '#FF0033',
},
},
},
yellow: {
colors: {
myBg: {
1: '#FFFFCC',
2: '#FFFF99',
3: '#FFFF33',
4: '#FFCC33',
},
myText: {
1: '#FFFFCC',
3: '#FFFF00',
2: '#FF9900',
},
myBorder: {
1: '#FF9900',
},
},
},
};
export const safelist = () => {
const arr: string[] = [];
Object.keys(myTheme.default.colors).forEach((item) => arr.push(...Array.from({ length: 10 }, (_, i) => `bg-${item}-${i}`)));
console.log(arr);
return arr;
};
3. uno.config.ts引入presetTheme
presetTheme会自动生成对应主题的变量
presetTheme<Theme>({
theme: myTheme,
}),
完整代码:
// uno.config.ts
import { defineConfig, transformerDirectives } from 'unocss';
import { presetUno } from 'unocss';
import type { Theme } from 'unocss/preset-uno';
import presetTheme from 'unocss-preset-theme';
import { myTheme, safelist } from './src/theme';
export default defineConfig({
// 预设
presets: [
presetUno(),
presetTheme<Theme>({
theme: myTheme,
}),
],
// 快捷方式, 将多个规则组合成单个简写
shortcuts: [
{
btn: 'py-2 px-4 font-semibold rounded-lg shadow-md cursor-pointer',
},
// 动态快捷方式
[/^btn-(.*)$/, ([, c]) => `bg-${c} text-#fff hover:bg-${c}/80 py-2 px-4 font-semibold rounded-lg shadow-md cursor-pointer`],
// 使用主题
[
/^mybd-(.*)$/,
([, c], { theme }) => {
return `b-1 b-${c} b-dashed`;
},
],
],
// 自定义规则
rules: [
// 注意:属性语法遵循 CSS 属性语法,例如 font-weight 而不是 fontWeight。如果属性名中有连字符 -,应该用引号括起来。
['font-bold', { 'font-weight': 700 }],
[/^bd-(\d+)$/, ([, d]) => ({ border: `${d}px solid #ddd` })],
[/^p-(\d+)$/, (match) => ({ padding: `${match[1]}px` })],
],
transformers: [
transformerDirectives(),
],
safelist: safelist() // 可以根据项目需要添加
});
4. App.vue添加主题切换
通过修改html的类名来实现主题切换,前面为了方便管理,我把uno.config.ts文件的主题配置给删掉了,全部移到了presetTheme的theme属性里,默认在index.html文件的html元素上加了default类名。
// App.vue
<script setup lang="ts">
import { ref } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
const radio = ref('default');
const onRadioChange = (e: string) => {
document.documentElement.className = e;
};
</script>
<template>
<el-radio-group v-model="radio" size="large" @change="onRadioChange">
<el-radio-button label="default" value="default" />
<el-radio-button label="red" value="red" />
<el-radio-button label="yellow" value="yellow" />
</el-radio-group>
<div class="wrapper">
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<HelloWorld msg="Vite + Vue" />
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
// index.html
<!DOCTYPE html>
<html lang="en" class="default">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
一个基本的主题切换功能到这就成功啦!!