Foreword
这两天看 Twitter 发现很多项目都是用 Uno CSS 来写样式,我之前一直觉得像 Tailwind CSS 这样的 CSS 框架反而会让项目变得过于烦琐,因其将一些样式拆分出来,独立样式,让其可以进行组合,class 会写的很长。
Tailwind CSS
阅读了 Tailwind 部分文档,其是通过使用功能类构建自定义设计而无需编写 CSS 来代替传统方式时,定制的设计需要定制的 CSS。
<div class="chat-notification">
<div class="chat-notification-logo-wrapper">
<img
class="chat-notification-logo"
src="/img/logo.svg"
alt="ChitChat Logo"
/>
</div>
<div class="chat-notification-content">
<h4 class="chat-notification-title">
ChitChat
</h4>
<p class="chat-notification-message">
You have a new message!
</p>
</div>
</div>
很容易看出传统的缺点,命名困难,可能会造成作用域冲突的问题;难以复用,某些语义下的 .title
可能包含多种样式,在同一语义环境下,也会因为上下文的差异导致无法直接复用 class;由于其不可复用的特性,会导致 css 的文件一直膨胀,甚至于超过代码体积,从而带来重构的成本增加。
<div
class="p-6 max-w-sm mx-auto bg-white rounded-xl
shadow-lg flex items-center space-x-4"
>
<div class="shrink-0">
<img
class="h-12 w-12"
src="/img/logo.svg"
alt="ChitChat Logo"
/>
</div>
<div>
<div class="text-xl font-medium text-black">
ChitChat
</div>
<p class="text-slate-500">
You have a new message!
</p>
</div>
</div>
看的出来 Tailwind 为了解决上面的痛点,设计出的这套系统,不再需要考虑命名问题,css 文件也不会膨胀,每一个 class 只对应一条 css 规则。这样 CSS 的原子性(Atomic CSS)可以使得 class 颗粒度更加容易的其他内容上进行复用,减少不同 html 标签的 class 之间的影响。
这套系统也可以通过 tailwind.config.js
文件进行拓展,例如可以通过 preset
添加自定义的基本配置,来替代 tailwind 的默认配置。
对于 Tailwind 还有很多其他内容,例如:响应式布局、使用功能类为处于悬停和其它状态的元素设置样式、DarkMode、函数与指令等,这些都是这个系统所具有的特点。当然并不是它是完美的,对于开发者而言,这套系统的配置项比较复杂,并且由于预先定义了大量的 CSS 类和样式,使得 CSS 体积非常庞大。
Uno CSS
为什么既然有了 Tailwind 为什么还需要 UnoCSS 呢?在这之前还有一个常见的原子类系统 windicss,它主要解决了上面提到 Tailwind 的一些痛点:
- 配置复杂:WindiCSS 的默认配置比较合理,而且很容易进行自定义配置,大大降低了配置的复杂度。
- 体积过大:WindiCSS 利用了 Just-in-Time (JIT) 编译技术,只会编译和加载用到的 CSS 类,从而减少了样式表的体积。
- 响应式设计复杂:WindiCSS 提供了一套响应式设计系统,开发者只需要根据需要添加相应的类名即可实现响应式布局,大大简化了响应式设计的复杂性。
- 可定制性差:WindiCSS 提供了丰富的配置选项,开发者可以根据自己的需求来自定义框架的样式、颜色、字体等各种属性。
但是 windcss 也不是万能的,为了兼容 Tailwind ,其配置项必须与 Tailwind 完全相同的配置,因此可能会造成为了拓展一些 class,例如:mt-2
,border-10
等,会导致生成 CSS 的代码比结果还要冗余,难以维护和阅读。
因此,才有了 UnoCSS(the instant atomic CSS engine with maximum performance and flexibility),但是官方的说明 UnoCSS 并非是一个框架,其是一个引擎,因为它没有提供核心的工具类,所有的功能都可以通过预设(preset)和内联配置(inline configurations)提供。
我认为预设特性是 UnoCSS 核心的一点,更加方便和快速地创建 Web 应用程序。开发人员可以根据需要选择其中的一种或多种特性,并根据实际情况进行定制,以满足应用程序的需求,因此可以使用 UnoCSS 自定义出自己的原子化 CSS 框架。
其他的一些特性(动态规则、静态规则、可修饰变量、作用域)我将不做过多的解释,官方文档更加详细,下面说明下为什么我会尝试使用 Atomic CSS。
Attempt
看了这些文章之后,开始抛弃旧的开发思维方式,尝试这些新的 css 引擎和框架。
在平时的开发中主要使用 scss 和 less 这种预编译器来写 css,在这当中会把一些常见的 css 通过一些函数表达来生成出来,例如:
@for $i from 1 through 4 {
.ml-#{$i} {
margin-left: #{$i}px;
}
}
我们也会用到部分原子化 css,这样确实在项目中可以很方便的统一边距的处理,但是这些给人的感受没有直接给出 .ml-1{ margin-left: 1px }
直观,往往很少有人去使用;其次,当项目中遇到了需要 ml-5
又需要去更改这个函数,难以阅读维护,其拓展性也不好;
当然,不仅仅是这一点内容,我最想尝试的是 UnoCSS 所提供的网格系统,轻松的创建出响应式布局。
更多可以查看 Unocss Github 进行的试验。
Reference
本文参考文章