フロントエンド素人が初めて触れるtailwind css

この記事は[株式会社アクシス Advent Calendar](https://qiita.com/advent-calendar/2020/mediaxis) 24日目です。

## はじめに

普段バックエンドばかり担当してるエンジニアがtailwindを触ってみて感じたことを、本記事で書いてみます。
tailwindのセットアップについては、他記事を参照していただければ十分だと思います。
また、webpackやlaravel-mixを通じた使い方は、それだけで一本の記事となりそうなので、ここでは扱いません。

参考
- [公式](https://tailwindcss.com/)
- [TailwindCSS入門 ~ Utility First + デザインシステムの構築 ~](https://qiita.com/oedkty/items/68461080515ec1012980)
- [最小手数で始めるTailwind CSS](https://tech.medpeer.co.jp/entry/better-tailwind-css)

tailwind css本体はminifyしても20M近くになる馬鹿でかいcssなんですが、PurgeCSSで削ぎ落とす前提なんですね。

### tailwind cssとは

- bootstrapとかと同じで、CSSフレームワークの一つです。
- `utility first`がコンセプトで、最近盛り上がってる…らしいです。
- 弊社のフロントエンドの人いわく「reactと相性よさそう」だそうな。

なお私は長年bootstrapしか知らず、それすらあまり触る機会が無いまま現在に至ります。
Laravelが8から導入したので、じゃあ触ってみるかという次第。先日記事を書いた[Laravel Breeze](https://qiita.com/nomuraxis/items/0791dfd3eea9c5ca4085)もtailwindでしたし。

### utility firstとは

今までのCSSフレームワークはパーツ、あるいはコンポーネントごとにクラスを定義してました。まずbootstrapの公式を一部引用してみます。scssなので`@include`とか入っちゃってますが。

https://github.com/twbs/bootstrap/blob/main/scss/_card.scss

```scss
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106
  height: $card-height;
  word-wrap: break-word;
  background-color: $card-bg;
  background-clip: border-box;
  border: $card-border-width solid $card-border-color;
  @include border-radius($card-border-radius);

  ...
}
```

クラス名から察するに、カードレイアウトのベースになるクラスでしょうか。一つのコンポーネントを表現するクラスにたくさんのスタイルが定義されてます。

で、大抵のプロジェクトでは、どの要素のwidthを何pxいじってほしいとか、大体どこかしらカスタマイズが発生します。
bootstrapはオブジェクト指向CSSで書かれているので、クラスの中に小クラスが定義されることも多々あります。その中の一部分を変えるための独自スタイルを複数人が書いたりして、やがてカオスなCSSに。

一方でtailwindだと1クラスプロパティの原則があります。
例えば、ごくシンプルな入力フォームを表示する場合、以下のようなコードになります。
(https://tailwindcomponents.com/component/join-form から引用)

```html
<!-- component -->
<!-- This is an example component -->
<div >
    <div class='flex justify-between min-w-xs max-w-sm w-full p-2 bg-white shadow-sm rounded-full overflow-hidden mx-auto'>
        <input type="text" class="outline-none min-w-sm p-2" placeholder="johndoe@mail.com"/>
        <button class="flex-end bg-blue-700 text-white font-semibold text-xl px-8 py-2 outline-none rounded-full text-center uppercase">JOIN</button>
    </div>
</div>
```

フォームにスタイルを当てたい時に`.form`クラスを定義・使用するのではなく、`flex`や`bg-white`といった単一プロパティのクラス = `utility class`をたくさん当てるのがtailwindです。
1クラスに1プロパティなのでhtmlに多数のクラスを記述する必要があり、一見するとこっちの方がbootstrapより混沌としてます。私は初見で割と驚いて「何これ」ってなりました。
htmlにstyle属性を直接書いてるような見た目ですが、あくまでクラスです。メディアクエリや`first:`, `:hover:`といったセレクタを定義したクラスも用意されてるので、コピペhtmlの量産でCSSガン無視のstyle属性も抑制できそうです。

bootstrapとtailwindの特徴をざっくり分けると

- bootstrap: いろいろなコンポーネントがあらかじめ用意されていて、そのまま使う分には便利だが、カスタマイズがつらい
- tailwind: コンポーネントを組むためのutilityなクラスが多数揃っていて、それらを組み合わせてコンポーネントを作る。カスタマイズは自由自在

という感じになると思ってます。
とはいえtailwindはutilityクラスの組み合わせを自分で決める必要があり、これはこれで別種のつらみがありますが、tailwindには**基本的に自分でCSSを書く必要がなく、CSSの混乱やクラス増殖を招かない**という、プロジェクトの運用では結構な利点があると感じてます。

## 実際に書いてみる

何の準備もせずhtmlやcssを書いて試せる[tailwindplay](https://play.tailwindcss.com/)を使ってみましょう。
[チートシート](https://nerdcave.com/tailwind-cheat-sheet)ももちろんあります。

まずはほぼ素のhtmlです。

```html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div>
      <form class="p-1">
        <input type="text" class="" placeholder="test@example.com"/>
        <button class="">submit</button>
      </form>
    </div>
  </body>
</html>
```
![スクリーンショット 2020-12-24 1.19.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854172/1caaf782-d9b4-525a-fd6a-e2cda4f9aa72.png)

`form`にだけ`p-1`クラスを当てています。pはpaddingで、数字部分は`rem`での指定になり、四方にpaddingを0.25remで設定することになります。数字を`px`にするとピクセル指定。

もう少しクラスを増やしてみましょう。

```html
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div class="flex justify-between shadow-sm rounded-full">
      <form class="p-3 m-3 rounded-lg bg-blue-100">
        <input type="text" class="rounded-xl p-1" placeholder="test@example.com"/>
        <button class="flex-end bg-blue-400 rounded-3xl text-center px-2 py-1">submit</button>
      </form>
    </div>
  </body>
</html>
```

![スクリーンショット 2020-12-24 1.37.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854172/ba60663c-9749-0e28-bf79-930625e62dfe.png)

各クラスの意味はチートシートで見ていただくとして、背景色や要素のradiusなど、多少スタイルを整えるだけでも、そこそこのクラスを当てることになりました。

上述したようにutility classを把握して組み合わせる手間はありますが、すでに多数のサンプルが存在します。
↑で出した[tailwindcomponents.com](https://tailwindcomponents.com/)は(多分)全てのコンポーネント例のコードが無料で確認できるので、おすすめです。
公式のコンポーネント集である[tailwind ui](https://tailwindui.com/)はbootstrapの有料/無料テーマ集のようなマーケットプレイスで、有料コンポーネントの方が多く、コードサンプルを探すには向いてないと感じます。

bootstrapは既成のクラスを下手にいじると事故る可能性がありますが、tailwindはクラスを組み合わせ、あるいは削除するだけで済むので、CSS同士の干渉が発生しにくい仕組みになってます。

エンジニア視点で見ると、総じてbootstrapよりはよほど取っつきやすい印象でした。
膨大なクラス名にも法則があるので、まあ使ってるうちに覚えるかなと。
簡単に拡張クラスを作ったりもできてしまうんですが、少なくともtailwindの命名規則が頭に入ってれば、フレームワークとの名前衝突はさほど起こらないと思います。

## プロジェクトにどう導入するか

### 考えなしに導入できるもんでもない

チュートリアルを少し触って、さてどうやってプロジェクトに取り入れるかを考えると、デザイナーにtailwindを使ってもらうのはそこそこ敷居が高いな…と感じています。
というのも、ざっと挙げるだけでもこれくらいの過程が必要なわけで。

- nodeとwebpackをデザイナーの環境にセットアップ
- tailwindへの習熟
- ~~デザイナーが過去にbootstrapカスタマイズで負った心の傷のケア~~

最後のは半分ネタですが、弊社デザイナーにtailwindの話をした時に、割と拒否反応が出てました。tailwindの特徴とか何も話さないうちにそうなってたので、もはやCSSフレームワークにいい印象が無さそう。
サンプル数が少なすぎるので断定はできませんが。

### 実際にコンポーネントを組み上げるには

CSSの知識が無いと何も作れません。例えば角が丸いボタンをsubmit要素として作る場合、border-radiusやら何やら、どんなプロパティを当てればいいのか、素のCSSを書く知識が無いと作りようがないです。
bootstrapなら`.btn`クラスひとつ当てればボタンを表示できますが、tailwindではあれこれクラスを当ててようやくそれらしいものが出来上がります。

### それでもtailwindを検討すべきか

やっつけでCSSをいじってきただけのバックエンド目線ですが、Yesだと思ってます。
複数のCSSファイルおよびクラス間の依存関係の管理から開放してくれて、規律をもたらすutility firstなフレームワークは、上述したコストを払ってでも導入を検討する価値があるんじゃないかなーと。
(10個以上のプロパティを装備したクラスをいじるなんて時、まず読み解くのが大変なので…)

とはいえ、そのフレームワークが必ずしもtailwindでなくてもいいのかもしれません。
今回調べてる過程で[chakra](https://speakerdeck.com/line_developers/modest-resistance-to-tailwind-css-starting-with-chakra-ui?slide=18)なるフレームワークの存在も知りました。
フロントエンジニア的にはこちらの方が好感度高いらしい。TypeScirpt、というかReactと相性がよさげなんだとか。
chakraも追っかける対象になりそうです。