公司内部 UnoCSS 培训文档,含日常使用小技巧,赶紧收藏起来!
前言
本人在生产项目中使用 UnoCSS 已经快两年了。前段时间在公司无脑整理了培训文档和我常用的一些小技巧,现在将排除项目内部代码之外的内容分享出来。
安装
在 Vue3 + Vite 项目中安装
安装 UnoCSS。
pnpm add -D unocss在 Vite 中注册插件。
// vite.config.tsimport UnoCSS from 'unocss/vite'import { defineConfig } from 'vite'export default defineConfig({plugins: [UnoCSS(),],})
创建 uno.config.ts 文件,当然你也可以直接在 vite.config.ts 中进行简单配置。
// uno.config.tsimport { defineConfig } from 'unocss'export default defineConfig({// ...UnoCSS options}
在 mian.ts 中导入。
// main.tsimport 'virtual:uno.css'
在 Nuxt 3 中安装
安装 UnoCSS 。
pnpm add -D @unocss/nuxt在 Nuxt 中注册模块。
// nuxt.config.tsexport default defineNuxtConfig({modules: ['@unocss/nuxt',],})
创建 uno.config.ts 文件,当然你也可以直接在 nuxt.config.ts 中进行简单配置。
// uno.config.tsimport { defineConfig } from 'unocss'export default defineConfig({// ...UnoCSS options})
此外,除了 Vue 和 Nuxt,UnoCSS 还支持 React、Next、Remix、Astro、Svelte、Webpack、PostCSS Plugin、uni-app 等。
UnoCSS 基础用法
交互式文档
交互式文档实际演示如下内容:
flex width colors mdn: padding & margin
基础语法
文字
<div class="text-4xl font-600 font-italic underline lh-tight">文字</div>
边框
<div class="border-2 rd-2xl border-dashed inline-block lh-10 text-4xl lh-20">文字</div>
边距
<!----><div class="p-x-4 py-8 mb-2 mt-3 inline-block border-2">边距</div>
宽高
<div class="w-40 h-30 border-2 py-2"><div class="h-full w-screen border-dashed border-1">宽高</div></div>
颜色
<div class="w-40 h-30 bg-stone p-2"><div class="bg-pink op-30 mb-2">背景</div><div class="bg-blue color-green p-2">颜色</div></div>
flex布局
<div class="w-xs"><h1 class="mb-2">Flex 布局</h1><div class="flex items-center justify-between border-1 mb-1 px-1"><div>flex-1</div><div>flex-2</div><div>flex-3</div></div><div class="flex items-center justify-end gap-3 border-1 mb-1 px-1"><div>flex-1</div><div>flex-2</div><div>flex-3</div></div><div class="flex flex-col gap-1 border-1 px-1"><div>flex-1</div><div>flex-2</div></div></div>
定位
<div class="w-xs border-1 p-2 relative">父元素<div class="absolute top-2 right-10 zindex-100">子元素</div></div>
动画
<div class="border-1 relative w-40 hover:transform-rotate-50 transition-all"><div class="transform-rotate-10 translate-x-10 cursor-pointer">动画</div></div>
important
<div class="w-xs border-1 p-2 text-4xl">父元素<div class="!text-2xl">子元素</div></div>
IDE 插件提示
Iconify SVG
官方文档:https://iconify.design/
官方图标库:https://icon-sets.iconify.design/
Icones 图标库:https://icones.js.org/
安装
pnpm add -D @unocss/preset-icons @iconify-json/[the-collection-you-want]我个人常用的是:@iconify-json/carbon 和 @iconify-json/remix。
如果你想开发模式下下载全部图标(它是按需编译的,不用担心编译后的体积):
pnpm add -D @iconify/json # 该全量包约为 130MB在 uno.config.ts 中配置 presetIcons 插件。
presetIcons({extraProperties: {'prefix': 'i-','display': 'inline-block','vertical-align': 'middle',// ...},})
UnoCSS 使用 SVG 图标
基础用法
通过 class 使用 SVG 图标。
<div class="p-4"><div class="i-carbon-3d-curve-auto-colon " /></div>
图标大小
<div class="p-4 flex items-center"><div class="i-ri-bluesky-line text-3xl" /></div>
颜色
<div class="p-4 flex items-center"><div class="i-ri-bluesky-line text-3xl color-blue" /></div>
切换效果
<div class="text-3xl i-twemoji-grinning-face-with-smiling-eyes hover:i-twemoji-face-with-tears-of-joy" />本地SVG压缩
如果需要进一步压缩本地 SVG 文件的体积,你可以安装 svgo 插件进行压缩。
pnpm add -g svgo通过命令:svgo -f path -o path 即可进行压缩处理。
更多压缩语法与配置文件请参考:https://github.com/svg/svgo/
UnoCSS Preset
Icons preset
你可以通过这个插件来使用 SVG 图标,前面在 ## Iconify SVG 章节已经介绍过了。
// uno.config.tsimport { defineConfig, presetIcons } from 'unocss'export default defineConfig({presets: [presetIcons({ /* options */ }),// ...other presets],})
下面是一些常用的配置项,更多内容需要参考官方文档。
通过 scale配置可以设置默认的缩放大小。通过 prefix可以设置 class 前缀。通过 extraProperties可以设置默认的 CSS 样式。
这是我的常用配置:
presetIcons({scale: 1.2,prefix: 'i-',extraProperties: {display: 'inline-block',},})
此外,该插件支持配置 CDN 加载、本地加载、按需加载和自定义 SVG 图标 class,具体参考官方文档:https://unocss.dev/presets/icons#configuring-collections-and-icons-resolvers。
Attributify preset
该插件提供 html 标签的attribute 写法支持。
// uno.config.tsimport { defineConfig, presetAttributify } from 'unocss'export default defineConfig({presets: [presetAttributify({ /* preset options */ }),// ...],})
配置后无需通过声明 class="" 也可书写样式,并且支持组合写法。
<buttonw-50bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"text="sm white"font="mono light"p="y-2 x-4 l-2 r-2 b-2 t-2"border="2 rounded blue-200">我不需要写 class</button>
这样的写法在常规的 html 标签上没有问题,如果是针对自定义的组件,如果组件内部封装的属性与样式冲突,则可以通过 un- 的前缀避免这个问题。
<MyText text="red">与组件的 text 属性冲突</MyText><MyText un-text="red">使用前缀设置颜色,不会冲突</MyText>
更多配置项和 TS 类型支持,请参考官方文档:https://unocss.dev/presets/attributify#typescript-support-jsx-tsx。
Web Fonts preset
UnoCSS 使用字体插件。
// uno.config.tsimport { defineConfig, presetWebFonts } from 'unocss'export default defineConfig({presets: [presetWebFonts({ /* options */ }),],})
该插件可以使用默认提供的字体,如 google``bunny``fontshare ,如果配置为 none 则使用系统默认字体。
下面是我的常用字体配置:
presetWebFonts({fonts: {sans: 'Inter:400,600,800',mono: 'DM Mono:400,600',},})
上面配置字体的写法为:font-sans
针对网络不好的环境或者需要自定义字体包的使用场景,插件支持通过 customFetch 手动配置:
// uno.config.tsimport { defineConfig } from 'unocss'import presetWebFonts from '@unocss/preset-web-fonts'import presetUno from '@unocss/preset-uno'import axios from 'axios'import ProxyAgent from 'proxy-agent'export default defineConfig({presets: [presetUno(),presetWebFonts({// use axios with an https proxycustomFetch: (url: string) => axios.get(url, { httpsAgent: new ProxyAgent('https://localhost:7890') }).then(it => it.data),}),],})
Rem to px preset
UnoCSS 所有的样式均为 rem 单位(value: 16px),如果不需要 rem 单位,可以通过该插件转成 px。
// uno.config.tsimport { defineConfig, presetRemToPx } from 'unocss'export default defineConfig({presets: [presetRemToPx(),// ...other presets],})
UnoCSS Transformer
Variant group transformer
该插件提供包裹多个 class 。
// uno.config.tsimport { defineConfig, transformerVariantGroup } from 'unocss'export default defineConfig({// ...transformers: [transformerVariantGroup(),],})
<div class="hover:(bg-gray-400 font-medium) font-(light mono)"/>上面的代码等同于:
<div class="hover:bg-gray-400 hover:font-medium font-light font-mono"/>Directives transformer
该插件提供在 css 里使用原子化 class。
// uno.config.tsimport { defineConfig, transformerDirectives } from 'unocss'export default defineConfig({// ...transformers: [transformerDirectives(),],})
使用 @apply或者--at-apply进行使用:
如果不想用默认的 --at-apply ,可以通过配置参数修改。
.custom-div {@apply text-center my-0 font-medium;}/* --at-apply 兼容性更好 */.custom-div {--at-apply: text-center my-0 font-medium;}
使用 @screen来开发响应式:
.grid {--uno: grid grid-cols-2;}/* @screen xs 会转成 --> @media (min-width: 320px) */@screen xs {}@screen sm {}/* 也可以使用 lt 设置 max-width */@screen lt-xs{}/* 也可以使用 at 设置 and */@screen at-xs{}
如果你需要使用主题,可以使用 theme()css 函数:
.btn-blue {background-color: theme('colors.blue.500');}
Attributify JSX transformer
插件支持在 JSX 合 TSX 中以属性写法写样式。
// uno.config.tsimport { defineConfig, presetAttributify, transformerAttributifyJsx } from 'unocss'export default defineConfig({// ...presets: [// ...presetAttributify(),],transformers: [transformerAttributifyJsx(), // <--],})
使用举例:
export function Component() {return (<div text-red text-center text-5xl animate-bounce>unocss</div>)}
Compile class transformer
插件支持将多个 class 编译成一个。
// uno.config.tsimport { defineConfig, transformerCompileClass } from 'unocss'export default defineConfig({// ...transformers: [transformerCompileClass(),],})
使用举例:
<div class=":uno: text-center sm:text-left"><div class=":uno: text-sm font-bold hover:text-red"/></div>
编译结果:
<div class="uno-qlmcrp"><div class="uno-0qw2gr"/></div>
.uno-qlmcrp {text-align: center;}.uno-0qw2gr {font-size: 0.875rem;line-height: 1.25rem;font-weight: 700;}.uno-0qw2gr:hover {--un-text-opacity: 1;color: rgb(248 113 113 / var(--un-text-opacity));}@media (min-width: 640px) {.uno-qlmcrp {text-align: left;}}
UnoCSS 常用使用技巧
shortcuts 组合 class
通过 shortcuts 将多个 class 组合成一个。该配置通常用于全局样式、主题、背景等。
export default defineConfig({shortcuts: [{'bg-main': 'bg-hex-eef5fc dark:bg-hex-0d1117','text-main': 'text-hex-555555 dark:text-hex-bbbbbb','text-link': 'text-dark dark:text-white ','border-main': 'border-truegray-300 dark:border-truegray-600',},{'text-title': 'text-link text-4xl font-800','nav-link': 'text-link opacity-70 hover:opacity-100 transition-opacity duration-200 cursor-pointer','prose-link': 'text-link text-nowrap cursor-pointer border-b-1 !border-opacity-30 hover:!border-opacity-100 border-neutral-500 hover:border-truegray-600 dark:border-neutral-500 hover:dark:border-truegray-400 transition-border-color duration-200 decoration-none','container-link': 'p-2 opacity-60 hover:opacity-100 cursor-pointer hover:bg-truegray-500 !bg-opacity-10 transition-colors transition-opacity duration-200',},{'hr-line': 'w-14 mx-auto my-8 border-solid border-1px !border-truegray-200 !dark:border-truegray-800',},]})
这是一个 Astro 项目中的一段示例代码
<html lang="en"><head><BaseHead {...head} /><ViewTransitions /></head><body class="bg-main text-main min-h-screen font-sans w-full bg-dot"><Header client:load /><mainclass="grow max-w-3xl mx-auto sm:pt-36 pt-26 pb-16 px-6 relative"transition:animate={fade({ duration: '0.4s' })}><slot /><ScrollToTop client:load /><Footer /></main></body>
响应式样式
通过 sm:xxx 等写法即可快速实现响应式样式。
如下面一段代码,在宽度大于 640px 时会隐藏菜单图标。
<div class="flex items-center h-full"><a href="/" mr-6 aria-label="Header Logo Image"><img width="32" height="32" :src="siteConfig.header.logo.src" :alt="siteConfig.header.logo.alt"></a><nav class="sm:flex hidden flex-wrap gap-x-6 position-initial flex-row"><av-for="link in navLinks" :key="link.text" :aria-label="`${link.text}`" :target="getLinkTarget(link.href)"nav-link :href="link.href">{{ link.text }}</a></nav><div sm:hidden h-full flex items-center @click="toggleNavDrawer()"><menu i-ri-menu-2-fill /></div></div>
其他媒体查询breakpoints前缀和对应的宽度如下:
sm, 640px lg, 1024px xl, 1280px
safelist与图标动态加载
在菜单或者动态配置的图标,以及动态 class 场景下,需要预加载图标才能正确显示。
可以通过如下方式实现:
使用 safelist;
import { defineConfig } from 'unocss'export default defineConfig({safelist: ['i-ri-file-list-2-line','i-carbon-campsite',],})
列出所有组合的对象,然后动态引用;
const classes = {icon1: 'i-ri-file-list-2-line',icon2: 'i-carbon-campsite'}
<div :class="classes.icon2" />通过配置文件
该方式,可以将所有的动态 class 放到单独的文件中,使用 // @unocss-include进行编译。
也可以配置 filesystem 指定文件。
// uno.config.tsexport default defineConfig({content: {filesystem: ['src/**/*.css',],},})
自定义 class 规则
通过配置 shortcuts 或者 rules 即可自定义规则。
通过 rules 即可覆盖默认的规则。
rules: [// 覆盖默认的规则['font-bold', { 'font-weight': 700 }],// 正则生成规则[/^m-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })],]
也支持选择器、特殊符号等生成,更多写法参考文档:https://unocss.dev/config/rules
通过 shortcuts 可以将多个 class 组合为单个 class。
shortcuts: {// 组合多条 class'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md',// 直接使用已经组合好的 class'btn-green': 'btn text-white bg-green-500 hover:bg-green-700',// 单个 class 声明别名'red': 'text-red-100',// 根据正则动态生成 class[/^btn-(.*)$/, ([, c]) => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`],}
自定义主题及覆盖
通过配置 theme 可设置主题系统,默认提供 tailwind css 或者 windi css 的主题。
theme: {// ...bgcolors: {'veryCool': '#0000ff', // class="text-very-cool"'brand': {'primary': 'hsl(var(--hue, 217) 78% 51%)', //class="bg-brand-primary"},},}
使用时:
<div class="bg-brand-primary"><a class="color-brand-primary">链接</a></div>
theme 配置支持覆盖媒体查询断点,如把 sm 修改为 320px。
theme: {// ...breakpoints: {sm: '320px',md: '640px',},}
class 自定义颜色值
如果 unocss 预设的颜色不能满足需求,可以通过如下方式自定义颜色值。
使用 class 直接声明颜色值, class="bg-#000 bg-hex-fff";使用 attribute 写法直接声明颜色值, bg="#000";
基于vueuse的黑暗模式
<i i="carbon-sun dark:carbon-moon" @click="toggleDark()" />常用 class 简写和写法
flex 简写, <div flex="~ items-center gap-2" />;margin 和 padding 简写,如: <div m-1 ml-1 mx-1 m-x-1 mt-1 mt-1.5px m="1 0" />;宽高度简写, <div h-1 h-auto h-full h-screen min-h-1 min-h-2vw max-h-50px />;负数, <div h--1 h--10px m--1 />;圆角, <div rounded rd-1 rd-full rd="1 0" />;!important, <div !flex />;鼠标样式, <div cursor-pointer />;禁用, <div disabled:cursor-default />;