ユーティリティーファーストとTailwind CSSのススメ


Tailwind CSSは結構いいんでないの?というポエムです

ユーティリティーファーストって考え方について

まず、

  • ユーティリティークラスが何かということ
  • ユーティリティークラスを使ってHTMLを書いていくということってどういうことか

これは、ある程度CSSを書いている人であれば想像できることであろうと思う。

こんな風に、あらかじめユーティリティー的なクラスを用意しーの

.align-left { text-align: left; }
.align-center { text-align: center; }
.align-right { text-align: right; }
.align-top { vertical-align: top; }
.align-middle { vertical-align: middle; }
.align-bottom { vertical-align: bottom; }
.mb-1 { margin-bottom: 1rem; }
.mb-2 { margin-bottom: 2rem; }
.mb-3 { margin-bottom: 3rem; }

これをHTMLに当てまくって画面を作ればほら簡単!お手軽に画面が作れるね!

と言う感じである。
これの良いところというのは、サクサク画面が作れること。これを体現したフレームワークにはAtomic CSS

というものがあって、Yahoo!ではこれを使って画面をサクサク作っていけるんだぜ!みたいな記事を2013年に見た。もう8年も前の話である。

CSSを書かなくても、どんどん自由にHTMLを作っていけると言うのだ。

このやり方でコードを書いていくには、まずある程度の学習コストが必要である。用意したユーティリティークラスをざっとでもいいので覚えなければならない。

しかし、いわゆるフツーにCSSを設計しようと思う実装者にとって、これは受け入れがたい所がある。なぜなら、この考え方は、BEMを代表とする、コンポーネントベースのCSS設計の考え方とは一線を画すからである。

うんうん、なるほどねサクサク作れるんだね、いいね〜〜〜〜って、
……こんなん受け入れられるかーーい!

って思うのである。たぶん多くのCSS書きは。
私もそうだった。過去形で。

私とTailwind CSS

筆者自身は、今はディレクター的な役割を仕事ではするのがメインであるが、CSSについては、IE5.5ぐらいからIE9ぐらいの時代まではずっとメインスキルとして書いてきた。CSS設計は好きなトピックで、色々調べてはどこかで話したり記事書いたり。コーポレートサイト中心にHTMLテンプレを延々作ってきたり。ただそれ以降はそんなにガリガリ書いていない。flexboxも見様見真似で書くし、メンバーが書いてるCSSを見て、へーなるほど今はこういうのもあるのね〜〜と言う感じである。

自分とCSS設計については、OOCSSの時代からBEMを経て、Enduring CSSと言うところで止まっていた。

正直、もうこのコンポーネントベースから先は、「どういう風にコンポーネントを設計するか」という、CSS設計よりも上のレイヤの話である。はっきりいってこれ以上CSS設計の話で新しいことはない。これ以上はCSSの話じゃないという認識でストップしていた。

そんな自分でも趣味でなにか書くことがあり、その場合はGatsby+Tailwind CSSで書いてきた。かれこれもう3回ぐらい。

Tailwind CSSで気付いてしまったこと

そんな自分、なんとなくTailwind CSSがいい感じだと思いつつもモヤモヤした気分を抱えたまま、何回か書いていくうちに、気付かされてしまった。Tailwind CSSに。

CSSを書いていた我々は、

  • まずは名前をつけてからスタイルを当てる
  • まずはHTMLとCSSで擬似的にコンポーネントを作る

そういうやり方に囚われすぎてしまっていたということを。

ユーティリティーファーストだと、これを逆にできる。

  • まずはスタイルを当てる
  • 2度以上使われたらコンポーネントとして考える

これが今はできるような時代になった。
Reactとか書いてたくせにそのことに気付けていなかった。

昔はこれができなかった。だからBEM的な方法になった。いや、そのときは間違いなくBEMでそれをするしかなかった。でも今は、その一歩先の時代になってる!

と、そう思ってる。

ユーティリティーファーストは今、CSS設計の最先端にあるものかもしれないと思うようになった。「こんなの受け入れられるかーい!」って思うはずのアレをである。

ユーティリティーファーストで書いていく例

んじゃまぁ、もう一度ユーティリティーファーストとはどういうことなのよと言うのを改めて。

具体的にはこういう感じで書く。
まずはひたすらユーティリティーで書くよねと。

<div class="bg-gray-600 p-12">
  <div class="flex bg-white rounded-lg p-6 shadow">
    <img class="h-24 w-24 rounded-full mx-0 mr-6" src="https://images.prismic.io/cgbook/9373859f-e98d-42f5-aa1e-9c328c16da2a_man.jpg?auto=compress,format" />
    <div class="text-left">
      <h2 class="text-lg">John Doe</h2>
      <div class="text-purple-500">Product Engineer</div>
      <div class="text-gray-600">[email protected]</div>
      <div class="text-gray-600">(555) 765-4321</div>
    </div>
  </div>
</div>

ここでBEM脳な人は、うわ、ないわ〜〜……ってなるのだが、待て待て。
そーいうふうにコードを書いていき、

あ、別のテンプレでこのUIがもう一度でてきたわ

ってなる。そしたら、

その時に初めてコンポーネント化する。

こう。

const MemberCard = ({ person }) => (
  <div className="flex bg-white rounded-lg p-6 mb-6 shadow">
    <img className="h-24 w-24 rounded-full mx-0 mr-6" src={person.img} />
    <div className="text-left">
      <h2 className="text-lg">{person.name}</h2>
      <div className="text-purple-500">{person.job}</div>
      <div className="text-gray-600">{person.email}</div>
      <div className="text-gray-600">{person.tel}</div>
    </div>
  </div>
)

おっとここで突然のReact登場〜。

え!? 今CSSの話してませんでした?

でもこれがTailwind CSSの考えるコンポーネント化なのだ。
その説明は以下でされている。

名前を考える必要がなくなっている

以降、これの何が良いのか?それをつらつらと書いていく。

まず、BEM的に考えれば、どこもかしこも名前名前である。要素一つ足すごとに名前を考える。でもこれって何でやってたんだ? こういう風に書き出した頃を思い出してみればそれは、「こういう風に半ば無理やりだけどカプセル化して、コンポーネントらしきものを作りたかった」からなのだ。

他と影響しないように色々工夫した結果がこのBEMっていう発明だった。この発明は画期的であり、ものすごい支持と評価を得て今に至っていると言える。でも今、ReactやVueがある世界では、この野望はひとつ上のレイヤで達成されてしまっている

クラス名って何のためにつけてたんだ?
これは、CSS設計的には、HTMLとCSSを結びつけ、CSSでスタイルを当てるためだろう。そして他と干渉しないように気を遣った。

ここで、改めてReactやVueコンポーネントの中身を考えて見て欲しい。ここでのクラスの役割というのは、BEM時代のそれとはだいぶ違う。この小さいコンポーネントと言う単位の中だけで、HTMLとCSSを結びつける以上の役割は期待されていない。

その上、CSS in JSなりCSS modulesなり、色々な技術が使えるようになった。えーとどうしたらいいんだ? 今まで俺たちが書いてきたBEMはなんだったんだ? 今、どう書いたら良いんだ? これでいいのか?クラスってなんだったんだ? 今まで通りSassで書いたらいいの? というようなモヤモヤとした思いがあるんじゃなかろうか。

ハイ、そこでユーティリティクラスのご提案です。

そうです、HTMLとCSSを結びつけるためのクラスの役割。
それはこういう感じが最適なのではないでしょうか?
あなた達、今まで必死にBlockとかElementとか名前考え続けてきましたけど、いまそんなに頑張る必要、もう無いんですよ。今、こういう感じがCSSの役割としてハマってるんじゃないでしょうか?

Tailwind CSSはそう言ってる気がする。今こういうコンポーネントコンポーネントできるようになったからこそ、ユーティリティークラスで書こうというのが可能になった気がする。だってやっぱり、8年前にYahoo!でAtomic CSSがすごいよっていう記事が出ても、みんなフーーーンだったじゃない。

コンポーネントの名前が難しい問題

CSS設計の世界には、以下の名前をどうすれば良いのか悩ましいという問題がある。

  • MediaBlock
  • ContactBlock
  • ProductInfo

どれもありえる。どうすりゃいい?

この答えは単純ではなく、「サイトやデザインの設計による」みたいなのが答えとして適当な所。後から変えるのはめちゃくちゃ辛いので、CSS設計は、コンテンツやデザインの設計との緻密なコミュニケーションが求められるとかどうとか、そういう話になってしまう。そこにしか解決方法はなかった。

あ〜CSS難しい難しい

ってなってた。
CSSの話じゃないのにね。
でもCSSうまく書ける人ってそういう人だったよ確実に。そういう話はAtomic Designを参照されると良いです。

でもこれ、ユーティリティーファーストで書いたら、もはや発生しない、と言うより、非常に薄くなる。なぜなら、繰り返しになるけど、

  • まずはユーティリティーで書く
  • 2度目に登場したらそこで初めてコンポーネント化する

ができるのである。

BEM的に書いてたのって何だったんですかね。
そう、あれは、そうしないと実装できなかったからなんだ。あらかじめ(疑似)コンポーネントで考えないと、作れなかったからなんだ。

でもこれには無理がある。そのひずみがこの「コンポーネントの名前が難しい」問題である。それに目をつむりながら、なんとか受け入れながらCSS書きはCSSを書いてきた。

ここで、BEM脳みそを捨てて考えよう。

そのコンポーネントが2度以上使われるかどうかなんて、その時はわからない

この当たり前の考えを受け入れよう。
今はそう考えて実装できるようになってるのだ。
ユーティリティーファーストで書けば、後からコンポーネントにする。そういうことができる。
この手順はさっき説明したとおり。

ユーティリティー「ファースト」ってそういうこと。

デザイシステム的なアレ

SassでCSSを書いているとしよう。

素敵なCSS設計者は、サイトで使われているフォントや色のパターンを洗い出し、パレットのような変数やmixinにして、統制を取ってくれる。デザイントークン的なアレだ。

さて、ReactやVueがある世界でこれをやろうとすると、何かしらの方法を使ってこういうことをやろうとするだろう。CSS in JSでどうこうしたり、方法は多種多様で、筆者はこのあたり突っ込んで見ていないから何がベストかは分からない。

でもこのあたり、そういう何かしらの謎CSSハック的なやり方を持ち出してこなくても、

  • React Component
  • HTML
  • ユーティリティクラス

この三段構えで完結させるのがシンプルでは?と思う。
Tailwind CSSを使えば、コンフィグを書けばデザイントークン的なクラスを作れる。

これを使えば、例えば

  • mb-md (Mサイズのmargin-bottom 20px)
  • mb-sm (Sサイズのmargin-bottom 10px)
  • mb-xs (XSサイズのmargin-bottom 5px)

みたいなのがお手軽にできる。

まぁ正直、Tailwind CSSの裏にはPostCSS君がいるわけで、この後ろのレイヤでゴニョゴニョやっているので、3段ではなく4段構えなんだが、こういうのをやるために、CSS in JSを持ち出したりするのって、オーバーすぎなのとちゃうんかい?

なんかそれ、もはや必要無いはずなのにBEM的なCSS設計+Sassな世界の文脈を引きずっているのでは? と思えてしまうのだがどうだろう。Tailwind CSSを見ていると、クラスって本来こういうものだったのでは? と思えてきてしまうのだがどうだろう。

そんなこんなで、筆者はどのCSS in JSも要らないと思う。Tailwind CSSと、いま時点ではたいして未来がなさそうだけど、scopedな感じに書きたいときはCSS modulesぐらいの単純さで十分なのでは?と思う。

あのーReactとかVueとか前提なんですか?

さっきからCSS設計の話かと思いきや、Reactとかの話してますよね?
Tailwind CSSって、そういうやつ前提なんですか?

と聞かれたら、自分的にはYesと答える。
というか、別にReactもVueも使わなくていいけど、例えば手書きでHTMLを作るみたいな要件の時にTailwind CSSを選んでしまうと、後で一括でスタイル更新したい時なんかに、200枚のHTMLを直して回ることになってしまう。

これはあからさまなデメリットで、これをカバーしてくれるのがReactなりVueなり、そこまでではなくても何かしらのテンプレートエンジンだったりCMSだったりするので、自分的にはそういうのが利用できないケースにおいては、Tailwind CSSを選択するのは、デメリットが気になりすぎて辛い結果になるのではと思います。

ワタシCSSヨクワカラナイ

さっき自分はCSS最近たいして書いてないって言ったんですが、そういう人にとってもTailwind CSSのドキュメントの充実っぷりは良いと思われる。

自分は

をChromeのショートカット作成でスタンドアローンのアプリみたくして、実装時には見ながらやってます。あーこういう風にしたらこういうレイアウトになるのねっていう。

それと、実装はVSCodeのTailwind CSS Intellisense頼みでして……なんとも貧弱なCSS力だなお前!と言われそうなのですが、まぁ正直それで書けるしそれでいいかなと言う感じであり、このようなスタンスでCSSを書いている人の割合はなかなかに多いのでは無いだろうか。そういう人らがある程度の割合でいるから、Tailwind CSSも支持されているのではないだろうかというのは思います。

かしこ。


以下で続きを書きました。