🔥 第一次在 React 项目中用 UnoCSS,这些坑我都踩了

入职第一周,我接了个新功能开发任务,正好有机会在项目里第一次上手 UnoCSS。 从引入、配置、实战使用到踩坑总结,这篇文章记录了我整个真实的使用过程,顺便分享一些经验和小技巧。


🧩 项目背景

我最近刚加入一家新公司,前端项目整体技术栈是 React + TypeScript + Vite,这次接手的新项目页面结构偏组件化,样式需求也不少。

公司之前在某些项目里尝试过 UnoCSS,但还没有大规模落地,这次正好借着新功能上线的机会,我也想趁机实战一把。 说实话,在真正动手用之前,我对原子化 CSS 一直有点抗拒:看着那一串串类名,总觉得乱,觉得"和写 style inline 没区别"。

不过这次我强行逼自己用上 UnoCSS,结果还挺香的。


🤔 为什么选择 UnoCSS?

虽然是新项目开发,样式量不算特别大,但要写得快、写得整洁、还要便于后续复用和维护,对样式方案的选择其实挺关键的。

调研阶段我也对比过几种方案:

样式方案 优点 缺点
SCSS / Less 成熟稳定,可自由写嵌套和变量 维护麻烦,类名容易重复,拆组件样式时要引入多个文件
CSS Modules 样式隔离,适合组件化 类名仍需维护,重复样式不易复用
Tailwind CSS 原子化、文档多、社区活跃 类名前缀多、需预定义主题、类名拼接繁琐
UnoCSS 类名极简、按需生成、配置灵活 学习成本稍高,文档偏底层,踩坑多

最终我选择了 UnoCSS,原因主要有 3 点:

  1. 按需生成类名,无需手动维护样式文件,更贴合组件开发节奏;
  2. vite 插件方式接入,配置极其轻量,基本无需额外操作;
  3. 可高度定制,可以自己写规则,自定义 class 变得更加简单。

一句话总结:想写得快、样式简单、还能灵活扩展,就选 UnoCSS。


⚙️ UnoCSS 是怎么引入项目的?

因为项目用的是 Vite + React,使用了 pnpm 管理,接入 UnoCSS 基本不费劲,几步就搞定了。

安装依赖:

ts 复制代码
pnpm add -D unocss

vite.config.ts 中添加插件:

ts 复制代码
import UnoCSS from 'unocss/vite'
​
export default defineConfig({
  plugins: [react(), UnoCSS()]
})

加几个常用 preset:

ts 复制代码
import { presetUno, presetIcons } from 'unocss'
​
UnoCSS({
  presets: [
    presetUno(),
    presetIcons()
  ]
})

我没有启用 attributify 模式,还是采用传统的 className 写法,这样团队其他人更容易接入。


💡 实际开发中怎么用?(Demo 示例)

UnoCSS 的写法跟 Tailwind 类似,但不需要提前扫描、构建就能直接生效,写起来轻松很多。

以下是我在 Demo 中使用 UnoCSS 的一些示例:

页面结构 + 样式一把梭

ts 复制代码
<div className="p-4 bg-white rounded shadow-md flex items-center justify-between">
  <span className="text-lg font-bold text-gray-800">标题</span>
</div>

按钮 hover 效果一把梭

ts 复制代码
<button className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">
  提交
</button>

响应式断点也拿捏

ts 复制代码
<div className="text-sm sm:text-base md:text-lg lg:text-xl">
  响应式文字大小
</div>

不用写 CSS 文件、也不需要维护类名、不担心污染,直接 className 组合就完事了。

除了常规写法外,UnoCSS 还支持非常强大的自定义规则,下面分享我项目中用到的一个实际例子。

✨ 自定义规则增强灵活性

UnoCSS 最让我惊喜的一点就是可以自定义规则。比如这次项目里有个地方要"多行文本省略",传统写法又臭又长。

我就直接在 uno.config.ts 里自定义了一个工具类:

ts 复制代码
// uno.config.ts
export default defineConfig({
  rules: [
    // 多行文本截断工具类
    [
      /^text-truncate-(\d+)$/,
      ([, lines]) => ({
        display: '-webkit-box',
        '-webkit-line-clamp': lines,
        '-webkit-box-orient': 'vertical',
        overflow: 'hidden',
        'text-overflow': 'ellipsis',
      }),
    ],
  ],
})

用的时候也很丝滑:

ts 复制代码
<p className="text-truncate-2">
  这是一个超长段落,将会被两行截断,超出的部分显示省略号......
</p>

是不是比用 SCSS 写变量还方便?尤其适合这种一劳永逸型的通用样式。


🐞 踩过的几个坑

虽然整体体验很好,但真用起来还是遇到几个坑,给大家踩过一遍,避免你也翻车:

动态类名无效

UnoCSS 是通过静态分析来生成类名的,像这种写法是不会生效的:

ts 复制代码
const size = 'lg'
return <div className={`text-${size}`}>文本</div>

解决方法是:

  • 静态写死可能的值;
  • 或配置 safelist 白名单:
ts 复制代码
safelist: ['text-sm', 'text-md', 'text-lg', 'text-xl']

IDE 无法提示类名

默认情况下 VSCode 不会自动提示 UnoCSS 类名,尤其是没有启用 attributify 的时候。 建议安装 UnoCSS 官方插件,并启用对应配置,能大幅提升开发效率。


📌 使用感受总结

经过这一轮实战,我对 UnoCSS 有了更完整的认识:

优点

  • 类名都是一眼能看懂的,看名字就知道样式;
  • 上手快,写一个类就能出效果;
  • 插件 preset 多,icons / shortcuts / web fonts 想用啥有啥;
  • 自定义能力强,几行代码搞定通用样式。

注意点

  • 动态类名需提前规划,避免运行时失效;
  • 公共样式建议封成 shortcuts;
  • 多人协作时需统一 className 命名习惯,不然易读性较差;

🤔 哪些场景适合用 UnoCSS?

  • 新项目从 0 起步,组件化程度高
  • 样式不重,但变化多,讲究效率的业务线
  • 团队能接受原子化类名这种写法

不太推荐的场景:

  • 老项目,已经铺了很多 SCSS 或 styled-components
  • 项目超重 UI,自定义样式太复杂
  • 团队成员完全没接触过原子化 CSS

✅ 最后总结

这次引入 UnoCSS 虽然只是新功能的一小步,但使用下来我真的觉得很爽:

  • 写得快;
  • 改得少;
  • 样式干净不乱;
  • 自定义很灵活。

跟 Tailwind 比,UnoCSS 更轻、更自由、更适合偏工程一点的团队。 如果你也在用 React + Vite,又想减少样式负担,真的可以试试看 UnoCSS。

如果你觉得这篇文章对你有帮助,欢迎点赞 👍、收藏 ⭐、评论 💬 让我知道你在看~ 我会持续更新 前端打怪笔记系列文章 ,👉 记得关注我,不错过每一篇干货更新!❤️

相关推荐
易鹤鹤.2 分钟前
openLayers切换基于高德、天地图切换矢量、影像、地形图层
前端
草明15 分钟前
解决: React Native iOS webview 空白页
react native·react.js·ios
可观测性用观测云34 分钟前
从“烟囱式监控”到观测云平台:2025 亚马逊云科技峰会专访
前端
bluemliu36 分钟前
django rest_framework 前端网页实现Token认证
前端·python·django
黄狗操作员38 分钟前
Django 创建APP urls.py path views.index 报错,NameError: name ‘views‘ is not defined
前端·python·django
gongzemin1 小时前
前端根据文件流渲染 PDF 和 DOCX 文件
前端·vue.js·express
jsonchao2 小时前
大厂失业后,我用cursor开发了第二款海外产品
前端·程序员
gnip2 小时前
低代码平台自定义组件实现思路
前端·低代码
实习生小黄2 小时前
基于扫描算法获取psd图层轮廓
前端·javascript·算法
青松学前端2 小时前
你不知道的秘密-axios源码
前端·javascript