Tailwind CSS on GitHub

功能类优先

在一组受约束的原始功能类的基础上构建复杂的组件。

概述

传统情况下,当您需要在网页上设置样式时,都需要编写 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;
    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;
    padding-top: 0.25rem;
  }
  .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 中应用预先存在的类来设置元素的样式。

使用功能类构建自定义设计而无需编写 CSS

ChitChat

You have a new message!

<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4">
  <div class="flex-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-gray-500">You have a new message!</p>
  </div>
</div>

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

  • 使用 Tailwind 的 flexboxpadding 功能类 (flex, flex-shrink-0, 和 p-6) 来控制整体的卡片布局
  • 使用 max-widthmargin 功能类 (max-w-smmx-auto) 来设置卡片的宽度和水平居中
  • 使用 background color, border radius, 和 box-shadow 功能类 (bg-white, rounded-xl, 和 shadow-md) 设置卡片的外观样式
  • 使用 widthheight 功能类 (w-12 and h-12) 来设置 logo 图片的大小
  • 使用 space-between 功能类 (space-x-4) 来处理 logo 和文本之间的间距
  • 使用 font sizetext color,和 font-weight 功能类 (text-xltext-blackfont-medium 等等) 给卡片文字设置样式

这种方法使我们无需编写一行自定义的 CSS 即可实现一个完全定制的组件设计。

我知道您在想:"这太繁琐了,真是一团糟!" 您是对的,这有点丑陋。实际上,当您第一次看到它时,几乎不可能认为这是一个好主意--您必须实际尝试一下。

但是,一旦您以这种方式实际构建了一些东西,您就会很快注意到一些真正重要的优点:

  • 您没有为了给类命名而浪费精力。 不需要仅仅为了设置一些样式而额外添加一些像 sidebar-inner-wrapper 这样愚蠢的类名,不必再为了一个 flex 容器的完美抽象命名而倍受折磨。
  • 您的 CSS 停止增长。 使用传统方法,每次添加新功能时 CSS 文件都会变大。使用功能类,所有内容都是可重用的,因此您几乎不需要编写新的CSS。
  • 更改会更安全。 CSS 是全局性的,您永远不知道当您进行更改时会破坏掉什么。您 HTML 中的类是本地的,因此您可以更改它们而不必担心其他问题。

当您意识到在 HTML 中使用预定义的功能类是多么的富有成效时,以任何其他方式工作都感觉像是折磨。


为什么不使用内联样式?

对这种方式的一个普遍反应是, "这不就是内联样式吗?" 在某些方面是 — 您是将样式直接应用于元素,而不是为元素分配一个类,然后在这个类中设置样式。

但是使用功能类比内联样式具有一些重要的优点:

  • 基于约束的设计. 使用内联样式, 每个值都是一个魔术数字。 使用功能类, 您是从预定义的设计系统中选择样式,这使得构建统一的UI变得更加容易。
  • 响应式的设计. 在内联样式中您不能使用媒体查询, 但您可以使用 Tailwind 的响应式功能类非常容易的构建完全响应式的界面。
  • Hover, focus, 以及其它状态. 内联样式无法设置 hover 或者 focus 这样的状态, 但 Tailwind 的状态变体使用功能类可以非常容易的为这些状态设置样式。

该组件完全响应,并包括具有 hover 和 focus 样式的按钮,完全由功能类构建:

Woman's Face

Erin Lindford

Product Engineer

<div class="py-8 px-8 max-w-sm mx-auto bg-white rounded-xl shadow-md space-y-2 sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:space-x-6">
  <img class="block mx-auto h-24 rounded-full sm:mx-0 sm:flex-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-gray-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>

可维护性问题

在使用功能优先的方式时,最大的可维护性问题是管理通用的可重复使用的功能类组合。

通过提取组件(通常做为模板片断或者组件),可以轻松解决此问题。

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

您也可以使用 Tailwind 的 @apply 功能创建抽象的 CSS 类。

<!-- Using utilities -->
<button class="py-2 px-4 font-semibold rounded-lg shadow-md text-white bg-green-500 hover:bg-green-700">
  Click me
</button>

<!-- Extracting classes using @apply -->
<button class="btn btn-green">
  Button
</button>

<style>
  .btn {
    @apply py-2 px-4 font-semibold rounded-lg shadow-md;
  }
  .btn-green {
    @apply text-white bg-green-500 hover:bg-green-700;
  }
</style>

除此之外,维护功能优先的 CSS 项目比维护大型 CSS 代码库要容易得多,因为 HTML 比 CSS 维护容易得多。诸如 GitHub,Heroku,Kickstarter,Twitch,Segment 等大型公司都在使用这种方法,且取得巨大成功。

如果您想了解其他人使用此方法的经验,请查看以下资源:

查看 John Polacek 策划的 The Case for Atomic/Utility-First CSS 了解更多信息。