1. 核心概念
  2. 工具优先的基础

概览

传统上,每当你需要在网页上进行样式设计时,你都会写CSS。

🌐 Traditionally, whenever you need to style something on the web, you write CSS.

使用传统方法时,自定义设计需要自定义 CSS

ChitChat

You have a new message!

<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>

<style>
  .chat-notification {
    display: flex;
    align-items: center;
    max-width: 24rem;
    margin: 0 auto;
    padding: 1.5rem;
    border-radius: 0.5rem;
    background-color: #fff;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  }
  .chat-notification-logo-wrapper {
    flex-shrink: 0;
  }
  .chat-notification-logo {
    height: 3rem;
    width: 3rem;
  }
  .chat-notification-content {
    margin-left: 1.5rem;
  }
  .chat-notification-title {
    color: #1a202c;
    font-size: 1.25rem;
    line-height: 1.25;
  }
  .chat-notification-message {
    color: #718096;
    font-size: 1rem;
    line-height: 1.5;
  }
</style>

使用 Tailwind 时,你可以通过在 HTML 中直接应用预设的类来为元素添加样式。

🌐 With Tailwind, you style elements by applying pre-existing classes directly in your HTML.

使用实用类构建自定义设计,无需编写 CSS

ChitChat

You have a new message!

<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center gap-x-4">
  <div class="shrink-0">
    <img class="size-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>

在上面的例子中,我们使用了:

🌐 In the example above, we’ve used:

  • 使用 Tailwind 的 flexboxpadding 工具类(flexshrink-0p-6)来控制整体卡片布局
  • max-widthmargin 工具(max-w-smmx-auto)用于限制卡片宽度并水平居中
  • 用于设置卡片外观的背景颜色边框圆角盒子阴影工具类(bg-whiterounded-xlshadow-lg
  • 用于设置徽标图片宽度和高度的 size 工具(size-12
  • 用于处理徽标与文本之间间距的 gap 工具(gap-x-4
  • 用于设置卡片文字样式的 字体大小文字颜色字体粗细 工具(text-xltext-blackfont-medium 等)

这种方法使我们能够实现完全自定义的组件设计,而无需编写一行自定义 CSS。

🌐 This approach allows us to implement a completely custom component design without writing a single line of custom CSS.

现在我知道你在想什么,“这简直是一场灾难,真是糟糕透了!”,你说的没错,这确实有点丑。实际上,第一次看到它时几乎不可能觉得这是个好主意——你必须亲自试一试

🌐 Now I know what you’re thinking, “this is an atrocity, what a horrible mess!” and you’re right, it’s kind of ugly. In fact it’s just about impossible to think this is a good idea the first time you see it — you have to actually try it.

但一旦你真的用这种方式构建了某样东西,你会很快注意到一些非常重要的好处:

🌐 But once you’ve actually built something this way, you’ll quickly notice some really important benefits:

  • 你不再浪费精力去发明类名。不需要再为了样式化某个元素而添加像 sidebar-inner-wrapper 这样无意义的类名,也不需要再为一个实际上只是弹性容器的东西纠结于找到完美的抽象名称。
  • 你的 CSS 不再膨胀。使用传统方法,每增加一个新功能,你的 CSS 文件都会变大。而使用工具类,一切都是可复用的,因此你很少需要编写新的 CSS。
  • 进行更改会更安全。CSS 是全局的,当你进行更改时,你永远不知道会破坏什么。HTML 中的类是局部的,所以你可以放心更改它们,而不用担心会破坏其他东西。

当你意识到只使用带预定义实用类的 HTML 工作可以如此高效时,以任何其他方式工作都会感觉像是折磨。

🌐 When you realize how productive you can be working exclusively in HTML with predefined utility classes, working any other way will feel like torture.


为什么不直接使用内联样式?(Why not just use inline styles?)

对于这种方法,一个常见的反应是想,“这不就是内联样式吗?”在某些方面确实如此——你是直接将样式应用到元素上,而不是给元素分配一个类名然后为该类设置样式。

🌐 A common reaction to this approach is wondering, “isn’t this just inline styles?” and in some ways it is — you’re applying styles directly to elements instead of assigning them a class name and then styling that class.

但是使用工具类比使用内联样式有几个重要的优点:

🌐 But using utility classes has a few important advantages over inline styles:

  • 在约束中设计。使用内联样式时,每个数值都是一个魔术数字。使用工具类时,你是从预先定义的设计系统中选择样式,这使得构建视觉统一的界面更加容易。
  • 响应式设计。你无法在内联样式中使用媒体查询,但可以使用 Tailwind 的响应式工具轻松构建完全响应式的界面。
  • 悬停、聚焦及其他状态。内联样式无法针对悬停或聚焦等状态,但 Tailwind 的状态变体可以让你轻松使用工具类来为这些状态设置样式。

该组件完全响应式,并包含一个具有悬停和聚焦样式的按钮,且完全使用工具类构建:

🌐 This component is fully responsive and includes a button with hover and focus styles, and is built entirely with utility classes:

Woman's Face

Erin Lindford

Product Engineer

<div class="py-8 px-8 max-w-sm mx-auto space-y-2 bg-white rounded-xl shadow-lg sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:gap-x-6">
  <img class="block mx-auto h-24 rounded-full sm:mx-0 sm:shrink-0" src="/img/erin-lindford.jpg" alt="Woman's Face" />
  <div class="text-center space-y-2 sm:text-left">
    <div class="space-y-0.5">
      <p class="text-lg text-black font-semibold">
        Erin Lindford
      </p>
      <p class="text-slate-500 font-medium">
        Product Engineer
      </p>
    </div>
    <button class="px-4 py-1 text-sm text-purple-600 font-semibold rounded-full border border-purple-200 hover:text-white hover:bg-purple-600 hover:border-transparent focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-offset-2">Message</button>
  </div>
</div>

可维护性问题(Maintainability concerns)

在使用以实用工具为先的方法时,最大的可维护性问题是管理常见的重复实用工具组合。

🌐 The biggest maintainability concern when using a utility-first approach is managing commonly repeated utility combinations.

这可以通过提取组件和局部文件以及使用像多光标编辑和简单循环这样的编辑器和语言功能轻松解决。

🌐 This is easily solved by extracting components and partials, and using editor and language features like multi-cursor editing and simple loops.

<!-- PrimaryButton.vue -->
<template>
  <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
    <slot/>
  </button>
</template>

除此之外,维护一个以实用工具为优先的 CSS 项目实际上比维护一个大型 CSS 代码库要容易得多,这只是因为 HTML 比 CSS 更易于维护。像 GitHub、Netflix、Heroku、Kickstarter、Twitch、Segment 等大公司都在使用这种方法,并取得了很大的成功。

🌐 Aside from that, maintaining a utility-first CSS project turns out to be a lot easier than maintaining a large CSS codebase, simply because HTML is so much easier to maintain than CSS. Large companies like GitHub, Netflix, Heroku, Kickstarter, Twitch, Segment, and more are using this approach with great success.

如果你想了解其他人对这种方法的体验,可以参考以下资源:

🌐 If you’d like to hear about others’ experiences with this approach, check out the following resources:

想了解更多,请查看由 John Polacek 精选的《支持原子/实用优先 CSS 的理由》(The Case for Atomic/Utility-First CSS)。

🌐 For even more, check out The Case for Atomic/Utility-First CSS, curated by John Polacek.