UnoCSS给了我一个不用tailwindcss的理由

2023-10-11
18407 分钟
...

如果你没有听说过 tailwindcss 或者 unocss,请先 return 先去了解一下😝。

  • 开发上:可能为你甚至你们的前端团队节省很多写样式的时间,也能让你或者你们的项目开发体验有很大提升
  • 生产上:你们的项目打出来的包体积中的样式代码占比将突然骤降然后趋于不变

书接上回

之前我写过一篇文章给我一个你不用tailwindcss的理由!,极力推荐使用 tailwindcss 来提升开发效率和体验,尤其是样式代码的体验会有质的提升。当然样式代码打包体积的减少也可以起到优化我们整体前端项目的作用。但是为什么有这篇文章了呢?因为托尼老师给了我不用 tailwindcss 的理由,无法拒绝的理由,就是我们今天的主角 UnoCSS

为什么我换到了UnoCSS

tailwindcssUnoCSS 都是原子化CSS模式实现的一种,为什么现在我更推荐 UnoCSS ,接下来就讲一下 UnoCSS 的杀手级亮点:

极致性能

这里我借用托尼老师的话:

No parsing, no AST, no scanning, it's INSTANT (5x faster than Windi CSS or Tailwind JIT).

跳过解析,不使用 AST

从内部实现上看,Tailwind 依赖于 PostCSS 的 AST 进行修改。考虑到在开发过程中,这些工具 CSS 的并不经常变化,UnoCSS 通过非常高效的字符串拼接来直接生成对应的 CSS 而非引入整个编译过程。同时,UnoCSS 对类名和生成的 CSS 字符串进行了缓存,当再次遇到相同的实用工具类时,它可以绕过整个匹配和生成的过程。

现在说是比 tailwindcss 快5倍,其实当年可是比 tailwindcss JIT 模式快200倍的存在,后面 tailwindcss 应该是做了大量的优化工作,才让托尼老师改口称5倍快了😜。

完全可定制,不是一个框架,而是引擎

相比于 tailwindcss 必须把原子类写到 class 里面, UnoCSS 提供了更多可选方案,并且兼容多种风格的原子类框架,除了 tailwindcss ,同样支持 BootstrapTachyonsWindi CSS

属性化模式

这个模式也是由 Windi CSS 启发而来: Attributify preset

// install 
pnpm add -D @unocss/preset-attributify  
// uno.config.ts 
import { defineConfig } from 'unocss'
import presetAttributify from '@unocss/preset-attributify'
export default defineConfig({ 
  presets: [     
    presetAttributify({ 
      /* preset options */
    }),    
    // ... 
  ],
})

🌰:

<div class="m-2 rounded text-teal-400" /> 
<!-- 现在你可以这么写--> 
<div m-2 rounded text-teal-400 />

前缀组,解决繁琐的多次写前缀的情况

Variant group transformer

typescript

复制代码

`// install pnpm add -D @unocss/transformer-variant-group  // uno.config.ts import { defineConfig } from 'unocss' import transformerVariantGroup from '@unocss/transformer-variant-group'  export default defineConfig({   // ...   transformers: [     transformerVariantGroup(),   ], })`

比如我们在设置字体的时候常常会设置颜色、大小,或者在 hover 的情况下改动多个属性我们就可以这样🌰:

html

复制代码

`<div class="hover:bg-gray-400 hover:font-medium font-light font-mono"/> <!-- 简化之后: --> <div class="hover:(bg-gray-400 font-medium) font-(light mono)"/>`

快捷方式和指令

Directives transformer

typescript

复制代码

`// install pnpm add -D @unocss/transformer-directives  // uno.config.ts import { defineConfig } from 'unocss' import transformerDirectives from '@unocss/transformer-directives'  export default defineConfig({   // ...   transformers: [     transformerDirectives(),   ], })`

用过 tailwindcss 的同学都知道, tailwindcss 有指令系统,其中的 @layer components 指令可以把通用的样式 layer 到一个类上:

css

复制代码

`@layer components {   .btn-blue {     @apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;   } }`

UnoCSS 有类似的更好用快捷方式来快捷实现这个功能:

ts

复制代码

``shortcuts: [   // you could still have object style   {     btn: 'py-2 px-4 font-semibold rounded-lg shadow-md',   },   // dynamic shortcuts   [/^btn-(.*)$/, ([, c]) => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`], ]``

另外还有一个使用很频繁的指令 @apply ,这个指令在以下两种情况下比较合适使用:

  • 有一个样式很多,很复杂的元素,直接写到标签里面会影响代码可读性
  • 同样的样式应用到很多元素上

🌰:

html

复制代码

`<div text-lg text-pink-400 font-bold border-1 border-gray border-dashed rounded flex flex-warp items-center justify-evenly>   我的样式很复杂的 </div> <button text-green-500 rounded hover:text-lg shadow-md>查询</button> <button text-green-500 rounded hover:text-lg shadow-md>提交</button> <button text-green-500 rounded hover:text-lg shadow-md>取消</button>`

就可以这么优化:

html

复制代码

`<div class="complex-node">   我的样式很复杂的 </div> <button class="btn">查询</button> <button class="btn">提交</button> <button class="btn">取消</button>  <style>  .complex-node {   @apply text-lg text-pink-400 font-bold border-1 border-gray border-dashed rounded flex flex-warp items-center justify-evenly; } .btn {   @apply text-green-500 rounded hover:text-lg shadow-md; } </style>`

构建合并多个原子类到一个类

Compile class transformer

typescript

复制代码

`// install pnpm add -D @unocss/transformer-compile-class  // uno.config.ts import { defineConfig } from 'unocss' import transformerCompileClass from '@unocss/transformer-compile-class'  export default defineConfig({   // ...   transformers: [     transformerCompileClass(),   ], })`

这个特性一般比较少用,也可以看下是什么作用,通过 :uno: 标记,可以最终编译为一个类:

html

复制代码

`<div class=":uno: text-center sm:text-left">   <div class=":uno: text-sm font-bold hover:text-red"/> </div>`

最终编译的结果:

html

复制代码

`<div class="uno-qlmcrp">   <div class="uno-0qw2gr"/> </div>`
css

复制代码

`.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: rgba(248, 113, 113, var(--un-text-opacity)); } @media (min-width: 640px) {   .uno-qlmcrp {     text-align: left;   } }`

检查器,可以详细的预览我们项目中的所有原子类

我们在启动开发服务器之后,可以直接访问localhost:5173/__unocss 就会看到这个画面:

直接就可以看到所有的原子类,具体某个组件中的原子类,打包后的体积等信息。

你的项目太老也想用?安排!

有些同学可能还在维护很老的前端项目,但是也想用上 UnoCSS 来提升开发体验, UnoCSS 提供了 CDN 版本,在前端的入口 index.html 文件中添加一行代码就可以支持,并且还支持配置💪:

html

复制代码

`<script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"></script> <script>  // pass unocss options window.__unocss = {   rules: [     // custom rules...   ],   presets: [     // custom presets...   ],   // ... } </script>`

VS Code 插件当然也有

UnoCSS - Visual Studio Marketplace

你以为到这里就结束了?

再来给你看个好东西!

Icons preset (unocss.dev)

可以在 UnoCSS 中轻松集成纯 CSS 图标,可以在这里查看所有可用图标,想用哪种就可以安装对应的包即可:

ts

复制代码

`// uno.config.ts import { defineConfig } from 'unocss' import presetIcons from '@unocss/preset-icons'  export default defineConfig({   presets: [     presetIcons({ /* options */ }),     // ...other presets   ], })`

没有你们设计中意的图标,UI 自己设计的图标也可以轻松集成,首先安装工具:

bash

复制代码

`pnpm install -D @iconify/utils`

然后把设计老师给的 svg 图标文件放到一个文件夹,我这里就放到src/assets/svg中,然后想一个图标名称,这里就叫 icon

ts

复制代码

`// unocss.config.ts import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders' import {   defineConfig,   presetAttributify,   presetIcons,   presetUno, } from 'unocss'  export default defineConfig({   presets: [     presetUno(),     presetAttributify(),     presetIcons({       collections: {         icon: FileSystemIconLoader(           './src/assets/svg',           svg => svg.replace(/#FFF/, 'currentColor'),         ),       },       scale: 1.5,       warn: true,     }),   ], })`

可以看到配置中 collections 里面有一个 icon 对象,这个名称就对应了我们刚才说的 icon 名称,对应的是一个 FileSystemIconLoader 方法,方法的第一个参数是你的图标在项目中的路径,我这里就是 ./src/assets/svg,按照相对路径就可以,也可以通过第二个参数做一些特殊预处理操作,具体可以看这个文档,这样配置完成之后,我们就可以在项目使用了。

比如我在src/assets/svg文件夹中放了一个 cancel.svg 的取消图标,我在页面上使用就可以这样写:

html

复制代码

`<div text-lg text-red inline-block i-icon:cancel />`

其中的 i-icon 就是我们前面配置的自定义图标集的名称,冒号后面跟的就是你的 svg 图标的名称,可以通过样式改变图标的大小和颜色,是不是很酷😎。

丰富、灵活、开放的预设生态

UnoCSS 提供了丰富的预设,以支持不同风格体系的前端开发者,生态很完善,在 UnoCSS 发布之后我在很多项目中都应用实践过,基本可以覆盖所有样式场景。

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
css2026-06-17
外阴影和内阴影介绍
在前端页面设计中,阴影是非常常见的视觉效果。它可以让元素看起来更有层次感,也可以用来表达悬浮、按压、凹陷、卡片、按钮等状态。 CSS 中最常用的阴影属性是 。它既可以实现外阴影,也可以实现内阴影。 一、什么是外阴影 外阴影指的是元素外部的阴影效果。 它会出现在元素边框之外,让元素看起来像是从页面中“浮起来”了一样。常见的卡片、弹窗、按钮悬浮效果,基本都会用到外阴影。 例如: 这个阴影表示:元素下方有一层柔和的黑色阴影,让卡片看起来更有立...
学习
css2026-05-15
border-image-slice详细介绍
是 CSS 系列属性里最关键、也最容易让人懵的一个属性。 它的作用可以简单理解为: 把一张图片切成九宫格,然后决定哪几块用来绘制元素的边框。 它通常和这些属性一起使用: 或者简写成: 其中 决定“怎么切图”。 一、 是什么? 普通的 只能画纯色边框: 但有时候我们想用图片作为边框,比如: 游戏按钮边框 像素风 UI 复古窗口 聊天气泡 卡牌边框 花纹装饰框 九宫格按钮背景 这时候就可以用 。 例如一张按钮图片长这样: 我们希望按钮变宽时...
学习
css2026-03-05
如何在最小副作用下创建 BFC
在 CSS 布局的江湖中, BFC (Block Formatting Context,块级格式化上下文) 是一个老生常谈却又至关重要的概念。无论是解决 高度塌陷 、 清除浮动 ,还是防止 垂直外边距重叠 ,BFC 都是我们的得力助手。 但是,创建 BFC 的方法有很多: 、 、 、 …… 哪种方法对现有布局的“破坏”最小? ❌ 过去的老方法 在过去,为了触发 BFC,我们不得不使用一些带有副作用的“黑客”技巧: : 元素会脱离文档流,...
学习
css2026-03-03
CSS过渡性能解析:transition: all
CSS过渡性能深度解析:为什么 可能是你页面的隐形杀手 一、引言:一个被忽视的性能陷阱 你是否曾在项目中这样写: 看似简洁优雅,却可能在低端设备上引发卡顿、掉帧。 真相 : 是前端性能优化中高频出现的“隐形陷阱”。本文将彻底揭开它的面纱。 二、核心概念: 到底在控制什么? 指定 哪些CSS属性变化时触发动画过渡 。它是过渡效果的“守门员”: | 值 | 含义 | 生成的CSS | | | | | | | 所有 可过渡属性变化时均触发动画...
学习
css2026-01-26
在CSS中,四种高度视口单位的区别
在CSS中,视口单位是构建响应式网页设计的重要工具,特别是针对移动端开发。除了传统的 ,CSS新引入了 、 和 等更精确的单位,解决传统单位在移动端的局限性。 四种高度视口单位的区别 | 单位 | 全称 | 含义 | 特点 | | | | | | | vh | Viewport Height | 传统视口高度单位,1vh = 视口高度的1% | 在移动端有问题:不考虑浏览器UI变化,经常导致内容被遮挡或出现意外滚动 | | svh |...
学习
css2025-11-04
keyframes 关键帧机制
一、什么是 @keyframes? 用于定义动画在不同时间点(关键帧)的样式变化;配合 属性应用到元素上。 定义动画 :使用 声明关键帧序列; 应用动画 :在选择器中通过 / 相关长属性控制表现。 二、基本语法 等价写法( / ): 三、与 属性配合使用 /相关长属性 | 属性名 | 含义 | 示例值 | | : | : | : | | | 动画名称 | | | | 持续时长 | 、 | | | 速度曲线 | / / / | | | 延...
学习

评论

请登录后发表评论

去登录
加载评论中...

目录