Tailwind CSSの設計思想を業務に活かす 前編 Tailwind CSSとそのCSS設計思想とは
前編後編の2回に分けて、CSSフレームワークのTailwind CSSとそのCSS設計思想を参考にしたCSS設計を話し合います。前編はTailwind CSSの設計思想とその特徴を語ります。
はじめに
最近話題に上がることも多いCSSフレームワークのTailwind CSSを取り上げ、CSS設計の課題やその解決方法の糸口を探っていく座談会です。
座談会はゲストとして、Tailwind CSSの作者のブログを翻訳した安田 祐平さんをお招きして行われました。
参加者は次のとおりです。
- 安田 祐平さん(株式会社シフトブレイン:フロントエンド・エンジニア)
- 中村 享介(株式会社ピクセルグリッド:Jamstackエンジニア)
- 高津戸 壮(株式会社ピクセルグリッド:フロントエンド・エンジニア)
- 坂巻 翔大郎(株式会社ピクセルグリッド:フロントエンド・エンジニア)
- 中野 祐人(株式会社ピクセルグリッド:Jamstackエンジニア)
(構成:編集、丸山陽子)
Tailwind CSSはどんなもの?
ーー今日はTailwind CSSの考え方を知ることで、今のCSS設計について考えていきたいと思います。ゲストにはご自身のブログなどでTailwind CSSに関することを執筆されている、安田 祐平さんにお越しいただいています。簡単に自己紹介をお願いできますでしょうか。
安田:シフトブレインという会社のフロントエンド・エンジニアです。コーポレートサイトとかメディアサイトとか、ページ数が多めのサイトの実装することが多いですね。Tailwind CSSは半年ぐらい前に作者のブログ記事を読んで、そこから意識していたというところです。自分のサイトで、そのブログ記事の翻訳も載せています。
安田 祐平さんのブログ
安田 祐平さんの個人サイトでは、「CSSにおける汎用化の先送り、ユーティリティファーストCSS、レイアウトプリミティブ」「翻訳:CSSユーティリティクラスと「関心の分離」(いかにしてユーティリティファーストにたどり着いたか)」といった、今回の座談会に関係した記事があります。ぜひご一読ください。
ーーよろしくお願いいたします。さて、Tailwind CSS。まず、どんなものなのか簡単に説明していただけますでしょうか。中野さんは、Tailwind CSSを使ってみているんですよね。
中野:はい、業務で使ったわけではないのですが、趣味サイトをTailwind CSSで書いたりしています。
Tailwind CSSはCSSフレームワークと呼ばれる類のものですね。UIコンポーネントを持たないでユーティリティクラスを組み合わせるので、デザイン上の制約がほかのCSSフレームワークよりも少ないことが特徴だと思います。個人的な使い心地としては「書きやすくなったインラインCSS」みたいな感じだと思っています。
坂巻:僕は(安田)祐平くんが書いたブログの「Taiwind CSSはCSSを書くためのフレームワークだよね」という一文がすごくしっくりきていて。
BootstrapとかBulmaだと画面を作っていくためのある程度できあがったコンポーネントが用意されてます。たとえばBootstrapのMedia object · Bootstrap v4.5を使うと「いい感じに画像が左にあってテキストが右にある」みたいなのが簡単にできますね。
でもTailwind CSSはそうはならなくて、HTMLを書くときにそこについでにCSSを書いているみたいな感じで書ける。CSSフレームワークといっても、Bootstrapとか、あとは最近のだとBulmaとは違うものだなって思います。
中野:それはすごくそう思います。そもそも思想の方向性が違うので、使っている層が違う気がして。今までBootstrapを重宝していた人たちって、たとえばサーバーサイド・エンジニアの方がフロントエンドを作るために簡単にCSSを書かなくても使えるみたいな文脈だったと思うんですけど、Tailwind CSSはCSSの知識がないとそもそも書けないので。どちらかというとCSSをより書きやすくするアプローチのものだと思うんですよね。
安田:そうですね、普通、CSSフレームワークというと、UIフレームワークみたいにある程度できあがったコンポーネントとかを提供するものだと思うんですけど、Tailwind CSSはレイヤーでいうと、CSS in JSとかそういう「CSSを書くためのもの」っていうイメージですね。
CSS設計の悩みとTailwind CSSのメリット
ーーTailwind CSSの考え方は、CSS設計においてどんなメリットがあるのでしょう。
安田:CSS設計というと常に困るのが、スタイリングをしようとすると、なにをするにも名前をつけなきゃいけない。名前をつけるところからしか始められないというのがあると思うんです。まずスタイルを書くにもセレクタを書かなきゃいけない。なにかしら名前をつけて、名前があってはじめてスタイリングできるというところです。
でも雑に名前をつけると後でむちゃくちゃになってくるし、そうかと言ってちゃんと名前をつけようとすると、それはそれで大変だということが常にあって。
高津戸:うん、うん。
安田:で、まあ、ある程度ページとか数を作っていると「これ、こういう感じかな」というのが見えてきたりするんですけど、このタイミングだと、名前をしっかりつけてしまうのが、微妙だなみたいなときがけっこうあって。「これ、名前つけるの後回しにしてスタイリングできないかなあ」みたいなことを思うことはあるんですよね。
高津戸:それは「そのUIは共通化されているのか? それともここでしか使わないように考えられたUIなのか?」ということですよね。その位置付けによって、クラスの命名が変わってくる。最初に「これは共通なのね」って汎用的な名前にしちゃうと「実はここでしか使いませんでした!」とかいうことが起こる。
安田:そうです。
高津戸:そのあたりが、いわゆるBEM的な流れ*の「コンポーネントに押し込めてやる」っていう考え方でいうと、難しいところがあるなあと思います。結局、CSS書く人がいろいろ空気読んでやったり、デザイナーに相談したり、ということになってしまう。
*注:BEM
BEMのCSS設計思想に関しては、次の記事なども参考にしてください。
- 「BEMによるフロントエンドの設計」シリーズ
安田:Tailwind CSSが目指しているところの一つに、整理するとか共通化するのが後回しにできるというところがあるんですよね。たとえば「適切な名前が見つかるまで」とか「本当に共通化する必要があるときまで」とか。
ひとまずはユーティリティのクラスでやっておいて、あとで必要になれば、たとえばテンプレートエンジンでパーツを切り出すとかっていうやり方で、必要なタイミングになってから共通化できるっていうところがあるんです。
高津戸:Tailwind CSS自体って、そういう共通化みたいな概念はあるんですかね?
安田:ツールとしてはPostCSSのプラグインがあります。Sassのミックスインみたいな感じで使えますね。セレクタを書いて、そこにインクルードしていくようにしてCSSを書ける仕組みがあるんですけど。
高津戸:なるほど。
中野:apply
*も使えますよね。apply
でTailwind CSSのクラス名を書いて、そのまとめたクラスをコンポーネントに書くみたいな。そういうことで共通化できますよね。
*注:apply
@apply
を使うことで複数のクラスをまとめ、まとめたクラスを再利用しやすくします。詳しくは、公式サイトの次のページを参照してください。
坂巻:ただapply
を使うためにはPostCSSが必要です。なので、CDNから読むタイプのTailwind CSSだとできません。Tailwind CSSをちゃんと使おうとすると、ビルドする仕組みありきになります。
安田:そのほかにコンセプトとして紹介されているのが、たとえばVueのコンポーネントに分けるとかですね。CSS側で全部整理するというよりは、テンプレートエンジンとかJSフレームワークの機能に乗っかって、それで共通化していくみたいなのが、けっこうフィーチャーされているかな、という印象です。
CSSを書ける人ほど書きにくい?
坂巻:ちょうど昨日、デモみたいなものを作る必要があって、Tailwind CSSを使ってみたんですよね。body
の中にform
とlabel
とinput
がいっぱい並んでいるみたいなページを作っていたんですけど、それにレイアウトを付けるのがめんどくさいので、Tailwind CSSでも使おうかと思ったんですけど。
ーーどうでしたか?
坂巻:すごいめんどくさい!って思っちゃって(笑)。普通に自分で書いたほうが速いんですよね。これくらいのページだと。
ーーなにがめんどくさかったんでしょうか?
中村:あれじゃない? 自分の中のCSSの知識を一回Tailwind CSSで調べるのがめんどくさかったんじゃない?
安田:最初はけっこう命名規則とか覚えないといけないんで。
坂巻:そうですね。それをすでに覚えていたら、もしかしたら速かった……かなあ。
高津戸:自分がTailwind CSSがアリだと思うのは、Tailwind CSSを覚えるということは、ReactとかVueを覚えましょうということとはわけが違うと思うからなんですよね。学習コストという意味でいうと、圧倒的に低いんじゃないかなと思いますけど。
あと、じゃあBootstrapを使うから覚えようってなったときに、Bootstrapのコンポーネントの名前を覚えてやっていくって大変じゃないですか。でもTailwind CSSだと、プロパティのもうちょっと先にあるレイヤーで、具体的すぎないユーティリティがある。それを覚えてサクサク作っていくのはアリなのかなーって思ったんですよね。
だから、げこたん(坂巻)がデモを作って時間かかった。でも一通り覚えたらいちいちスタイル書いてなくていいし、楽だ!って思うのかもなって思うんですよね。想像なんですけど。
中村:のっち(中野)も使っていたよね。どうでした?
中野:はい。僕は、坂巻さんの「Tailwind CSS書くのはめんどくさい」っていうのは、慣れの問題も大きいかなと思います。
たとえば「ここをdisplay:flex
にしたいんだけど、Tailwind CSSではどう書くんだろう?」とか、どう書くのかを調べる手間が入るじゃないですか。いくらわかりやすく作られていても。そこの慣れだと思うんですよね。
ただ、Tailwind CSSは、margin
がm
でpadding
がp
とか、記法が一貫しているんですよね。たとえばmargin-top
が.mt
で、margin-right
が.mr
とかみたいな感じで、CSSの知識がもともとあれば簡単に入ってくる。最初のそこを越えると、だいたい調べなくてもできるような領域にはなる。そうすると、速くなると思います。
Tailwind CSSの独自の書き方
安田:Tailwind CSSは、HTML側でスタイルを書くみたいな感じなんですよね。だから要素型セレクタを書いたら全部適用されるみたいなのと逆です。普通にセレクタを書くのと逆方向の書き方というか。
坂巻:ああ……!
中村:HTML側でスタイルを書くから、HTML側でうまいことコンポーネント化されていないとつらいんですよね。同じものの繰り返しだとしたら、同じコンポーネントにしてある必要があって、そこが共通化されていれば一箇所書くだけで全部変わるはず、ということなので。HTML側のコンポーネント化は前提になるんだろうなと思いますね。
高津戸:確かに。そうしないと、ほんとに大昔のOOCSSが「こうやったらだめだ!」といっている例でしかない*。Reactコンポーネント内にあるh2
のスタイルを設定するためにTailwind CSSを使っても、コンポーネント外のh2
には何も影響しなくて問題ないって感じですね。
*注:こうやったらだめな例
OOCSSで説明される「こうやったらだめ」な例は、次の記事を参照してください。
坂巻:全然問題ないですよね。
中野:そうですね、Gatsbyなどを使えばReactの構文を使って静的サイトも作れるようになったっていう文脈で、便利になっている感じなんですね。
高津戸:そうそう。それは大きいのかなって思うんですよね。そもそもこの座談会をやろうと思ったきっかけが、ピクセルグリッドの社内勉強会でパフォーマンスの話をしたことからなんですよね。たとえばSPA作ると大きなJSがどうしてもできてしまうので、最初の読み込みが遅いということがありますよね。でも、最近だとJamstackのGatsbyJSだとかNext.jsとかでは、ページ単位でJSを考えるからパフォーマンスも改善されるっていうことがあります。
その流れで、じゃあCSSはどうやって書くのがいいんだろう? という話になったんですよね。CSS in JSもあるし、JSのようにページ単位でまとめるという考え方もある。そこで、最近Tailwind CSSとか出てきたよねっていう話になったんです。
Tailwind CSSは最近ですけど、昔はAtomic CSSなんかもあったじゃないですか。僕は当時は「これはぜんぜんナシだなー」って思っていたんです。でも、OOCSSとかBEMとかそういうものが目指すものって、コンポーネントをCSSで作っちゃうということですよね。昔はクラス名をかなりセマンティックな、コンポーネントを意識したBEMみたいなものにするのって、人の手で指定したりとか書いたりするから、それがないとつらかったと思うんです。
*注:OOCSSとBEM
OOCSSもBEMもCSS設計の考え方のひとつです。次のシリーズなども参照してください。
でも今って静的なサイトを作っていく上でも、人の手で書いてがんがんページを作っていくことがほとんどないなと思っています。たとえば、Jamstackみたいな構成を採用するのであれば、GatsbyやNext.jsなんかだとReactベースでなんで、JSXで書けるからその中でループを書けますし、Eleventy*を使ったりして、テンプレートエンジンがあるなら、そういうループをスマートに書ける機能はあるのが当たり前です。
*注:
Eleventyについては、次のシリーズなども参照してください。
- 「静的サイトジェネレーターEleventy」シリーズ
それにReactとかVueを使うなら、そもそもそのライブラリ自体にコンポーネントという概念があるので、CSS設計のレイヤーでBEMみたいなコンポーネントを設計する意味が薄れてくる。それだったら、そのコンポーネントの中で抽象化するTailwind CSSみたいなほうがいんじゃないの? って思ったんですよね。
安田:そのテンプレート機能のおかげで、クラス名をセマンティックにする必要がなくなってきたみたいな感じがありますよね。
高津戸:そうそう。結局、コンポーネントの中でクラス名を考えると、item
とか抽象的なのが繰り返されるのを使うだけになる。外に影響しないから。でも、そうすると、そもそもそれをやる意味自体ないのかなって思ってきて。そう考えると昔はこれはどういう名前がイケているのかを時間をかけて考えていたのが、別にやらないでもいいんじゃないの? ってなってきたんですよ。僕個人が。
不要なCSSをどうするか
ーーなるほど、今の設計に合っている部分も多そうなTailwind CSSですが、逆にデメリットというか、気になる点はありますか?
坂巻:Tailwind CSSで僕が気になっているのは、使っていないCSSがあるっていうことですね。
安田:そうですね。使っているクラスだけを抽出するPurgeCSSみたいなツールがあるんですけど、それを使って「いらないやつは削りましょう」と言っていますね。
坂巻:なるほどね。
安田:考え方で言うと、Atomic CSSがいい対照になるかなと思います。Tailwind CSSだとあらかじめクラスが用意されていて、使っていないやつは削るみたいな感じになるんです。Atomic CSSだとAtomic CSSにするためのツールが提供されていて、Atomic CSSの記法でHTMLにクラスを書くと、逆にCSSを生成するんですよね。なので、必要最小限の実際に使われているクラスだけをCSSに生成できるようになっていますね。
高津戸:Tailwind CSSにはそういうのはない?
安田:そうですね。ないです。
中野:そういう意味でも、ほかのフレームワークと併用するというのがいいわけですね。Gatsbyでもgatsby-starter-tailwindという、スターターみたいのをインストールすると、その段階でPurgeCSSが入っているんで、自動でいい感じにしてくれるようになりますよね。こんなところからも、フレームワークが流行っているところで、Tailwind CSS、いいよねってなっているんでしょうね。
高津戸:Tailwind CSSなら、用意されてるクラスをすべて使う*なんてことはまずなさそうだし、PurgeCSSかけたら、そうとう容量少なくなりますよね。たぶん。
*注:Tailwind CSSを全部読み込んだら?
ちなみにTailwind CSSをすべて読み込んだ場合のファイルサイズは、次の公式ドキュメントを参照してください。
坂巻:そうですね。
高津戸:コンポーネントのCSSがそこにいっぱい入っていたら、何百KBとか、1MB超えたとかになることかもしれないんだけど、Tailwind CSSレベルのちっこいやつの集まりだったら、そこまで問題にはならないのかなという気がしますよね。
中野:そうですよね。だからパフォーマンスにもよさそうかなという気持ちもあります。
高津戸:なるほど。あと、自分が気になるのがTailwind CSSは実務で使えるか? ということなんですよね。そのあたり、どうでしょうか。
(後編に続く)