💎

【Tailwind和訳】CORE CONCEPTS/Utility-First

2021/10/23に公開約7,200字

この記事について

この記事は、CORE CONCEPTS/Utility-Firstの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

ユーティリティ・ファースト

制約されたプリミティブ・ユーティリティーのセットから複雑なコンポーネントを構築する。

概要

従来、ウェブ上で何かをスタイルする必要があるときは、CSS を記述していました。

カスタムデザインにカスタム CSS を必要とする従来の方法では
Image from Gyazo

<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 を書かずにカスタムデザインを構築する
Image from Gyazo

<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ユーティリティ(flexflex-shrink-0p-6)を使って、カード全体のレイアウトを制御しています。
  • max-widthmarginユーティリティー(max-w-smmx-auto)で、カードの幅を制限し、水平方向に中央に配置しています。
  • 背景色境界線の半径ボックスシャドウユーティリティー(bg-whiterounded-xlshadow-md)でカードの外観を整える。
  • ロゴ画像のサイズを調整する高さユーティリティー(w-12h-12)
  • space-betweenユーティリティー(space-x-4):ロゴとテキストの間のスペースを調整する。
  • カードテキストのスタイルを決めるフォントサイズテキストカラーフォントウェイトユーティリティー(text-xltext-blackfont-mediumなど)

この方法では、カスタム CSS を 1 行も記述することなく、完全にカスタムなコンポーネントデザインを実装することができます。

さて、「これは非道だ、なんてひどいことをしているんだ!」とお考えの方もいらっしゃると思いますが、その通り、ちょっと醜いですよね。実際のところ、最初にこれを見て良いアイデアだと思うことは不可能で、実際に試してみる必要があります。

しかし、実際にこの方法で何かを作ってみると、すぐにいくつかの重要なメリットに気づくでしょう。

  • クラス名を作るためのエネルギーを無駄にしなくて済むsidebar-inner-wrapperのような馬鹿げたクラス名を、何かのスタイルを作るためだけに追加したり、実際には単なるフレックスコンテナであるものに完璧な抽象的な名前をつけるために悩んだりする必要がなくなります。
  • CSS の成長が止まる。従来の方法では、新しい機能を追加するたびに CSS ファイルが大きくなってしまいます。ユーティリティではすべてが再利用可能なので、新しい CSS を書く必要はほとんどありません。
  • より安全に変更できる。CSS はグローバルなものなので、変更したときに何を壊しているかわかりません。HTML のクラスはローカルなものなので、他のものが壊れることを心配せずに変更できます。

定義済みのユーティリティークラスを使って HTML だけで作業することがどれほど生産的であるかを理解すると、他の方法での作業は拷問のように感じられるでしょう。

なぜインラインスタイルを使わないのか?

このアプローチに対する一般的な反応は、「これはインラインスタイルに過ぎないのではないか」というもので、ある意味ではその通りです。要素にクラス名を割り当ててそのクラスにスタイルを付けるのではなく、要素に直接スタイルを適用しています。

しかし、ユーティリティクラスを使用することで、インラインスタイルに比べていくつかの重要な利点があります。

  • 制約のあるデザイン。インラインスタイルを使用すると、すべての値がマジックナンバーになります。ユーティリティでは、あらかじめ定義されたデザインシステムからスタイルを選択するため、視覚的に一貫した UI の構築が非常に容易になります。
  • レスポンシブデザイン。インラインスタイルでメディアクエリを使用することはできませんが、Tailwind のレスポンシブユーティリティーを使用すれば、完全なレスポンシブインターフェースを簡単に構築することができます。
  • ホバー、フォーカス、その他のステート。インラインスタイルでは、ホバーやフォーカスなどのステートをターゲットにすることはできませんが、Tailwind のステートバリアントを使えば、ユーティリティクラスでそれらのステートを簡単にスタイリングすることができます。

このコンポーネントは完全にレスポンシブで、ホバーとフォーカスのスタイルを持つボタンを含み、すべてユーティリティクラスで構築されています。

Image from Gyazo

<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 の抽象化を行うことができます。

Image from Gyazo

<!-- 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 コードベースを維持するよりもはるかに簡単であることがわかります。GitHub、Heroku、Kickstarter、Twitch、Segment などの大企業がこのアプローチを採用し、大きな成功を収めています。

このアプローチを採用した他の企業の経験談をお聞きになりたい方は、以下の資料をご覧ください。

さらに詳しい情報は、John Polacekが監修したThe Case for Atomic/Utility-First CSSをご覧ください。

Discussion

ログインするとコメントできます