Skip to content

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 详细查看