TailwindCSSを触ってみて感じたユーティリティクラスの考え方について

株式会社エイチームフィナジーのAdvent Calendar 2021 14日目の記事です。


## 前章
TailwindCSSを触って1年ほど経ちます。TailwindCSSを触って感じたことは、以前までのユーティリティクラスの考え方とTailwindCSSでのユーティリティクラスの考え方が全く違うことに驚きがありました。
TailwindCSSを触る前と後でのユーティリティクラスの考え方についてまとめてみます。
結論からいうとユーティリティクラスをいろいろ調べたり、考えたりしてみて、以下二つに分類されるのではないかという結論に至りました。

ユーティリティファースト：TailwindCSSにあるような、ユーティリティクラスだけで構成する考え方。
ユーティリティセカンド：ユーティリティクラスは存在するが、極力使わないor最終手段の考え方。

## 前提｜ユーティリティクラスとは
HTMLの要素やコンテンツの役割に直結しない、どこでも使用できる汎用の装飾クラスを指します。

## 前提｜TailwindCSSとは
CSSフレームワークです。Bootstrap、MaterialUIなどがあります。これらと大きく違うのはTailwindCSSは、ボタン、メニュー、パンくずリストなどのいわゆる役割の概念でクラスは用意されていません。例外はありますが、一つのCSSプロパティに一つのクラスがあります。

## AtomicDesignを模した独自のフレームワークでの考え方
CSSを構築する際に、TailwindCSSを触る前は独自のフレームワークを流用していました。
その際はAtomicDesignの考え方、atoms（原子）、molecules（分子）、organisms（生体）、templates（テンプレート）、page（ページ）という具合の粒度で設計を行なっていました。

[図解]![Frame 15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283056/88390c27-e918-2679-81ad-ca2ce7de8574.png)

```scss:style.scss
//以下より変数定義
@import "variables";//ブレイクポイントの変数やカラー変数、Easingなど
@import "functions";
@import "mixins";
@import "reset.scss";//リセットCSS読み込み。
@import "vendor/*";//プラグインのCSSを入れる。
//..etc
//以下からサイトを構築する部分
@import "object/utilities/*";//ユーティリティクラス
@import "object/atoms/*";//btnなどの原子要素
@import "object/molecules/*";//cardなどの分子要素
@import "object/organisms/*";//headerなどの生体要素
@import "object/templates/*";//分子を組み合わせた役割、モジュール
@import "object/pages/*";//各ページで個別に設定すべきもの
```
###この時のユーティリティクラス
上記の独自フレームワークでは以下でユーティリティクラスを展開しています。

```scss
@import "object/utilities/*";//ユーティリティクラス
```

ここで展開されるものは以下のような便利で使い勝手の良いものです。

```scss:margin.scss
@for $i from 1 through 100 {
  u-m-t-#{$i}{
    margin-top: #{$i}px !important;//importantが重要
  }
}
...etc
```

この設計でのユーティリティクラスはあくまで最終手段の便利なクラス、そして、最優先としてCSSを当てるものとして使用することになります。そのため、！importantを使用しており、ユーティリティクラスは必要最小限、最終手段で使います。ユーティリティセカンドの考え方です。

![Frame 16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283056/2eca057f-35e4-687d-f4de-17e614bde727.png)


## TailwindCSSでのユーティリティクラス
前置きが長くなりましたが、TailwindCSSのユーティリティクラスつまりユーティリティファーストとは、ユーティリティクラスしか存在しないので、以下のような考え方になるかと思います。

![Frame 17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283056/c16b91fa-f862-e23a-f4e5-8b641643b05e.png)

```scss
@import "object/utilities/*"; //考え方としてはこれだけ
//なのでDOMに<script src="https://cdn.tailwindcss.com"></script>を読み込みましょう。
```

TailwindCSSの素晴らしいところは、原子レベルと分子レベルどちらで構築すればいいのか・・・・という悩み自体がなくなります。

[TailwindCSSユーティリティクラス一覧](https://nerdcave.com/tailwind-cheat-sheet)
TailwindCSSで実装されたコードは以下、公式サイトを参照ください。[TailwindCSSサンプル](https://tailwindcss.com/docs/utility-first)

## ユーティリティファーストで困ること１｜使い回すようなコンポーネントはどうするのか？
通常のCSSを構築するとき、いかにCSSコンポーネントにできるかがCSS破綻を免れる大きな要素になるか思います。そういった構築を意識することで、同じような要素を違うページにも簡単に複製することが可能です。しかし、ユーティリティフィーストの場合、同じものが他のページにあったとしても、再度ユーティリティクラスをつけて構成することが必要になります。

```scss
.a-title{
  border-bottom:2px solid blue;
  font-size:22px;
  display:inline-block;
  padding:0 8px;
  font-weight:bold;
}

//<h2 class="a-title">タイトル1です</h2>
//<h2 class="a-title">タイトル2です</h2>
//<h2 class="a-title">タイトル2です</h2>
```
```html:TailwindCSSの場合
<h2 class="border-b-2 border-blue-800 inline-block px-2 text-xl font-bold">タイトル1</h2>
<h2 class="border-b-2 border-blue-800 inline-block px-2 text-xl font-bold">タイトル2</h2>
<h2 class="border-b-2 border-blue-800 inline-block px-2 text-xl font-bold">タイトル3</h2>

```
上記見て頂いた通り、TailwindCSSではコンポーネントという概念はありません。そのため非常使いまわすときは不便です。しかしながら、Reactなどでコンポーネント化することで対応可能となります。

## ユーティリティファーストで困ること２｜CSSファイルサイズ
ユーティリティクラスだけだと、ファイルサイズが大きくなりすぎるのではないかと思われると思います。
結論からいうと「はい」です。ほとんどのCSSプロパティが網羅されているクラスとが用意されているわけですから、それら全てCSSファイルとして読み込ませる以上、かなりのサイズになるかと思います。ただ、TailwindCSSにはpurgeCSSが搭載されていて、ページ毎にユーティリティクラスを監視し、未使用のユーティリティクラスは読み込むCSSファイルから削除する機能です。例えば、TOPページにアクセスするとき、利用されていないユーティリティクラスはCSSファイルからは除外し、クライアントに送信するTOPページ用のCSSファイルを用意することができます。これにより、通常よりはるかに軽いCSSファイルが作成されます。
TailwindCSSを使用する上でpurgeCSSはなくてはならない機能だと思います。

## まとめ
TailwindCSSv3.0がリリースされました。CDNで使えたりと、便利な機能が続々追加されているフレームワークですし、なにせCSSのどう構築しようかという考えがなくなって、直感的にスタイルを当てることができます。
大規模サイトではなかなか導入するのは難しいかもしれませんが、Reactと組み合わせることで大きな開発コスト削減になるかと思います。