sakamotoko blog

たぶんweb系の技術ブログ @skmtko

ユーティリティークラスベースのcss設計に抵抗感があった俺を、それを使いたい俺が説得する

Tailwind CSSいいなあ熱が自分の中で高まっているので、Tailwind CSSの根幹でもあるユーティリティクラスベースのcss設計について書いてみます。 (ユーティリティクラスベースじゃなくて、Tailwind CSSではユーティリティファーストっていっているけど、まあいいか)

f:id:skmtko:20200525132325p:plain
ユーティリティークラス 結構いいやつなんやなと感じてきた...

cssに関してreact、vueとかのコンポーネントベースのフロント実装をしっかり始める前までは、スクラッチでフロント開発を行う際には、FLOCSSやら、SMACCSやらのCSS設計思想に基づいて、ガッチガチのCSS設計をして、CSSの崩れや破綻を根絶する!と息巻いていました。

というのも、3年とか前の話です。

その後reactを書き始めると、css_modules, styledComponents などの恩恵で、そこまでガチガチな、css設計思想が不要になって来ます。

ユーティリティクラスとは何

クラス名がそのまま、cssのプロパティとその値をそのまま表現しているもの。 例えば極端な話、margin-top-10px とかをdiv要素に当てると、そのままmargin-top: 10px を 指定することができるというもの(本当はそんなそんな直球な命名じゃなくて、mt-4 みたいな感じだけど)

FLOCSS(https://github.com/hiloki/flocss)では以下の様に説明されています。

ComponentとProjectレイヤーのObjectのモディファイアで解決することが難しい・適切では無い、わずかなスタイルの調整のための便利クラスなどを定義します。 Utilityは、Component、ProjectレイヤーのObjectを無尽蔵に増やしてしまうことを防いだり、またこれらのObject自体が持つべきではないmarginの代わりに.mbs { margin-bottom: 10px; }のようなUtility Objectを用いて、隣接するモジュールとの間隔をつくるといった役割を担います。 またclearfixテクニックのためのルールセットが定義されているヘルパークラスも、このレイヤーに含めます。

つまり、ユーティリティークラスは、あくまで補助としての役割である。

これだけみると、「ユーティリティークラスベースでcss書いていくとかどういうことやねん」です。

話は変わってきた

「ユーティリティークラスベースでcss書いていくとかどういうことやねん」だったわけだったんですが、話しは変わってきました。

まずそもそも、なぜユーティリティークラスを補助として使わなかったのか、それはなるべく要素に対して、少ないクラス名をつけることでスタイリングをしたかったから。 例えば、list とつければリストの見た目になって欲しかったし、リストの子要素はlist__item とつければちゃんとした見た目になって欲しかったから。

同じ部品を作るために、同じクラスをつける必要があったから。

でも、vueやreactならば、部品(コンポーネント)を呼び出せば、特に毎回classを当てなくても(component内部でclassを当てたりはしてるはずだけど)、listはリストの見た目をしてくれるし、list__itemはリストの子要素の見た目をしてくれる。 さらにcssModulesや scoped style や styledComponents を使えば、componentの中に影響範囲を絞ることもできる幸せ

コンポーネントにスタイルが閉じ込められているのではれば、たとえばコンポーネント内で

<div class=“display-block background-color-blue border-rardius-50 border-1px border-style-solid border-color-bloack box-sizing-border-box margin-none padding-10px”>

みたいなえげつないクラスをつけていても、同じような部品を使いたいときは、その部品をきっと呼び出すだろうし、 コンポーネントの呼び出し先ではきっと、コンポーネント命名が正しければそれで良くて、きっと中身のクラスに関してはクラスの命名なんて全く気にしないはず。

みたいな感じで、コンポーネントベースでの実装においては、CSS命名規則はそこまで厳格にガッチガチにする必要はないのでは?(コンポーネントが適当に分けられていて、かつちゃんと命名されていれば)

駄目押し

割とここまでで、個人的に結構ユーティリティークラスベースいいやんとなってきましたが、駄目押しに Tailwind CSS のドキュメントで紹介されいる利点をあげます。

" You aren't wasting energy inventing class names. "

クラス名に悩む必要がない! 明確に main-content とか list-card とかがあるんだったら良いけれど、ドキュメント内で例であげられている様な、sidebar-inner-wrapper の様な「おそらくレイアウトのために生まれたんだろうなあ...」な要素に対してのクラス名に悩ませる必要がなくなります!幸せ。

" Your CSS stops growing. "

CSSが成長し続けることがない!
そりゃあそうですね、普通に画面やパーツが増えるごとにcssを追加していけば、cssの量はどんどん増え続けます。基本的にユーティリティークラスを再利用してスタイリグを進めていくので、cssの増加はほとんどないはずです。

" Making changes feels safer. "

変更が怖くない!
cssはグローバルに影響を及ぼします。そのために、命名記法を厳格に設計し名前空間を区切るなどをして、なんとかそれを回避するぞするんですが、ユーティリティークラスベースならば、基本的に要素へのクラスの追加、付け替えしか起きないはずなのでグローバルのstyleに影響を及ぼさない。つまり変更により他のクラスを壊してしまう心配がありません。

まとめ

ざっくりとこんな感じの理由で、ユーティリティークラスベースのcss設計やりたくなりました。 多分他にも旨みや、これだから「ユーティリティークラスベース」でも心配ないとか多分きっとあると思いますが、結局はフロント開発を進める上でcssとHTMLとで構造を二重で管理するのが辛かんったんだなあとしみじみ感じました。

参考

GitHub - hiloki/flocss: CSS organization methodology. Utility-First - Tailwind CSS CSS Utility Classes and "Separation of Concerns" 翻訳 - Qiita