CSS 样式一直是消耗前端工程师战力的一员猛将,我们总是在思考命名和组合属性之间不断消耗着,直到最近发现了一个有些另类的 CSS 框架——TailwindCSSopen in new window(并不是它出现得晚,而是我发现得晚😂),或许能带来一些启发。

TailwindCSS 另类在哪里

常用的 CSS 框架通常以功能单元作为划分依据,将一部分 CSS 属性组合在一个或多个类名中,以达到开箱即用的目的。

如,使用 Bootstrap4 中的基础进度条需要两个类名 progressprogress-bar,它们的 CSS 属性如下:

.progress {
    display: -ms-flexbox;
    display: flex;
    height: 1rem;
    overflow: hidden;
    font-size: .75rem;
    background-color: #e9ecef;
    border-radius: .25rem;
}
.progress-bar {
    display: -ms-flexbox;
    display: flex;
    -ms-flex-direction: column;
    flex-direction: column;
    -ms-flex-pack: center;
    justify-content: center;
    overflow: hidden;
    color: #fff;
    text-align: center;
    white-space: nowrap;
    background-color: #007bff;
    transition: width .6s ease;
}

可以看到,每个类名都是一堆 CSS 属性的组合,需要时直接使用类名即可:

<div class="progress">
  <div class="progress-bar"></div>
</div>

而 TailwindCSS 不一样,它将 CSS 中的常用属性都分别用一个或多个类名封装起来,让用户自行组合,以实现想要的功能。

在 TailwindCSS 中实现同样的进度条,可能的写法如下:

<div class="flex overflow-hidden rounded h-4 bg-gray-300">
  <div style="width: 50%" class="flex flex-column justify-center text-center overflow-hidden bg-black rounded transition-all duration-300 ease-in-out"></div>
</div>

可以看到,TailwindCSS 的使用方式是完全的自由组合!

那么,另类的 TailwindCSS 又有哪些优缺点呢?

优点

首先来看看 TailwindCSS 的优点。

代码复用率高

TailwindCSS 已经为很多属性预定义类了,在使用时可以随意组合,甚至无需再添加额外的 CSS 代码,代码复用率非常高。

可高度自定义

TailwindCSS 虽然已经提供了非常多的预设类,但还是不可能满足所有需求,因此 TailwindCSS 提供了 npm 包,让我们可以任意定制。

首先安装 TailwindCSS:

# Using npm
npm install tailwindcss

# Using Yarn
yarn add tailwindcss

接着在 CSS 文件中引入:

@tailwind base;

@tailwind components;

@tailwind utilities;

提示

@tailwind 是 TailwindCSS 自定义的指令。

然后创建一个配置文件 tailwind.config.js

module.exports = {
  important: true,
  theme: {
    fontFamily: {
      display: ['Gilroy', 'sans-serif'],
      body: ['Graphik', 'sans-serif'],
    },
    extend: {
      colors: {
        cyan: '#9cdbff',
      },
      margin: {
        '96': '24rem',
        '128': '32rem',
      },
    }
  },
  variants: {
    opacity: ['responsive', 'hover']
  }
}

在这个配置文件中,我们可以对 TailwindCSS 做任意配置,如字体设置、增加类、减少类、调整配色、调整间距、断点设置等,一如平时使用 CSS 预编译器定义各种变量一样(个人觉得,TailwindCSS 也可以算是预编译器)。

最后将 CSS 编译出来:

npx tailwindcss build styles.css -o output.css

编译出来的 output.css 包含了所有 CSS,在 HTML 中直接使用类名即可。

TailwindCSS 不仅可以独立使用,也可以作为插件与 PostCSS 集成,或者在 WebpackGulp 等构建工具中使用,详情可点此open in new window查看。

体积小

这里所说的体积小不是指 TailwindCSS 本身小,相反,如果引入全库,TailwindCSS 体积足有 783.5kb,即使使用 Brotliopen in new window 压缩后也有 22.6kb,更不要说我们再自定义一些类了。

好在可以通过使用 Purgecssopen in new window 来移除未使用的类,大大减小体积,详情可点此open in new window查看。

在不增加自定义类的前提下,整个项目完成后最小可以做到仅有一个 CSS 文件,无论有多少模板,都不会增加 CSS 代码,因此从 CSS 的角度来看,体积是大大减小了。而与此同时,HTML 中的代码会相应增加,因为完成一个元素的样式设置需要使用更多的类名。

不过,最终的 CSS 代码是会有标点符号及浏览器前缀的,与这相比,类名增加造成的体积增加小多了。

缺点

接着来看看 TailwindCSS 的缺点。

类名太多,难以记忆

这应该算是 TailwindCSS 最显著的缺点了,但本质上也并不是太大的问题,使用 Bootstrap 或者其他 UI 框架(甚至于组件)时,我们依然需要翻阅文档查看类名及 HTML 结构,使用 TailwindCSS 也一样,而且 TailwindCSS 的文档也非常清晰。

无法从 HTML 中看出区块结构

如果在 HTML 中直接使用 TailwindCSS 提供的类名,那么元素上的类名会非常多,我们很难看出其区块结构,这对于后期的维护会造成一些困难。

例如,我们有一个卡片组件如下:

card

其 HTML 代码可能为:

<div class="flex w-1/4 border border-teal-600 rounded p-4 items-start shadow-lg">
  <div class="flex-shrink-0 mr-5">
    <img class="w-40 rounded" src="./cat.jpg" alt="">
  </div>
  <div>
    <h2 class="font-bold text-blue-800">这是一只猫</h2>
    <p class="text-gray-500">
      猫,属于猫科动物,分家猫、野猫,是全世界家庭中较为广泛的宠物。家猫的祖先据推测是起源于古埃及的沙漠猫,波斯的波斯猫,已经被人类驯化了3500年(但未像狗一样完全地被驯化)。</p>
  </div>
</div>

在 Vue 或者 React 中,我们第一反应肯定是将其封装成一个组件,但即便是这样,时间长了又或者另一个同事接手这个项目,仍需要花费大量时间来理解这些类名的含义。

TailwindCSS 对此也有考量,并提供了函数与指令open in new window来解决这一问题。

我们可以使用更具语义化的自定义类名,

<div class="card">
  <div class="card-left">
    <img class="card-img" src="./cat.jpg" alt=""/>
  </div>
  <div class="card-right">
    <h2 class="card-title">这是一只猫</h2>
    <p class="card-abstract">猫,属于猫科动物,分家猫、野猫,是全世界家庭中较为广泛的宠物。家猫的祖先据推测是起源于古埃及的沙漠猫,波斯的波斯猫,已经被人类驯化了3500年(但未像狗一样完全地被驯化)。</p>
  </div>
</div>

然后在自定义类名中应用 TailwindCSS 中的类:

.card{
  @apply flex w-1/4 border rounded p-4 items-start shadow-lg
}
.card-left{
  @apply flex-shrink-0 mr-5
}
.card-img{
  @apply w-40 rounded
}
.card-right{

}
.card-title{
  @apply font-bold text-blue-800
}
.card-abstract{
  @apply text-gray-500
}

TailwindCSS 会将预设类名所表示的属性注入到我们自定义的类名中,最终得到的代码和平时书写的 CSS 代码一样,如 .card 最终的代码如下:

custom_class

当然,如果我们不考虑语义化,这个缺点也就不存在了。

兼容性

TailwindCSS 仅兼容到 IE11,如果项目对兼容性要求较高,肯定是没法使用的,也算是一个小缺点吧。

待定

除了前述的优点与缺点外,TailwindCSS 还有一些不太容易确定的点。

使用成本

使用成本在这里是一个变量,与 UI 设计和项目大小有很大的关系,简言之:项目大、设计重复率高则使用成本低,反之则使用成本高。

结语

其实这种将属性尽可能多的预定义成类名的方式,我在刚进入前端领域的时候也干过。那时被命名折磨得不轻,而且回头一看,各个类名中的很多属性还都是一样的,就试着把每个属性都定义成一个类名,直接使用即可。

不过没多久,又发现与 BEM 命名规范相去甚远,从类名可以大致看出其所表示的属性,但却无法做到在 HTML 中看出区块结构,因此还是放弃了。现在想想,终究是自己考虑不周😂。

至于 TailwindCSS 是否真的好用,还需大家自行尝试。线上实例可以访问 GitLabopen in new window

最近更新:
作者: MeFelixWang