稀土掘金技术社区

公司内部 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 基础用法

交互式文档

Image

交互式文档实际演示如下内容:

  • flex
  • width
  • colors
  • mdn:
  • padding & margin

基础语法

  • 文字
<div class="text-4xl font-600 font-italic underline lh-tight">  文字</div>

Image

  • 边框
<div class="border-2 rd-2xl border-dashed inline-block lh-10 text-4xl lh-20">  文字</div>

Image

  • 边距

<!---->
<div class="p-x-4 py-8 mb-2 mt-3 inline-block border-2"> 边距 </div>

Image

  • 宽高
<div class="w-40 h-30 border-2 py-2">  <div class="h-full w-screen border-dashed border-1">宽高</div></div>

Image

  • 颜色
<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>

Image

  • 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>

Image

  • 定位
<div class="w-xs border-1 p-2 relative">  父元素  <div class="absolute top-2 right-10 zindex-100">    子元素  </div></div>

Image

  • 动画
<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>

Image

  • important
<div class="w-xs border-1 p-2 text-4xl">  父元素  <div class="!text-2xl">    子元素  </div></div>

Image

IDE 插件提示

Image

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>

Image

  • 图标大小
<div class="p-4 flex items-center">  <div class="i-ri-bluesky-line text-3xl" />  </div>

Image

  • 颜色
<div class="p-4 flex items-center">  <div class="i-ri-bluesky-line text-3xl color-blue" />  </div>

Image

  • 切换效果
<div class="text-3xl i-twemoji-grinning-face-with-smiling-eyes hover:i-twemoji-face-with-tears-of-joy" />

Image

本地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="" 也可书写样式,并且支持组合写法。

<button  w-50  bg="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>

Image

这样的写法在常规的 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 proxy customFetch: (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 />            <main              class="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">    <a      v-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>

Image

其他媒体查询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: {  // ...  bg  colors: {    '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 />;