MyブームCSS論
はじめまして。Web界隈に生息するmirilinと申します。
今回は最近使っている・良さそうと思っているCSSの設計手法や考え方について書いてみたいと思います。
紹介するのは、BEM+RSCSS、そして新たな「追い風」Tailwind CSSです。
BEM+RSCSS
BEM
言わずと知れたBEM。歴史も長く使っている人も多いためすでに共通認識となっていると言っても良いでしょう。私も昔から愛用しています。
BEMの詳細について今回は割愛します。
RSCSS
・本家
・日本語訳(本家に日本語翻訳と紹介されていた記事です。現在は移転したため本家からは飛べなくなってしまったようです。)
RSCSSの基本的な考え方はBEMとほとんど同じです。
公式でもこれはアイデア集だとされていますが、個人的にはBEMをもっと良くするアイデアだと思っています。
具体的な内容の解説は本家にお任せするとして、ここが良い!というところをいくつか紹介します。
・Componentsの命名規則
BEMでいうblockにあたるComponentsに、2単語以上からなる命名をすることとしています。これは複数単語のユニークな命名をすることで、名前のバッティング防止に有用です。
・Elementsは1単語
例えばこのElementsを2単語以上にしたいと思ったときはもう新たなるComponentsの誕生と考えられ、明確な指標とすることができます。
複数の単語もOKとされていますが上記の理由からできるだけ1単語にすると意識すると良いと思います。
・Variant
BEMのModifierと同じ用途ですが、ダッシュ(-)のprefixで独立しておりBEMより簡潔に書くことができます。また、明確なprefixをつけることでComponentsやElementsと差別化されています。
・Layoutの概念
Componentsは異なるコンテキストで再利用できるべきであり、位置や大きさ、マージンなどのポジションに関するプロパティを書くのは避けます。
これは非常に重要な考え方で、コンポーネントがコンポーネントを内包するときに、親は子にどんなコンポーネントが来るか知らない(知るべきではない)ということです。コンポーネントとは独立しておりどこででも使えるものなので、親子の依存関係を作らないことが重要になります。
・ファイル単位でひとつのComponent
ファイル単位で分けることで、コンポーネントが可視化され、どこに何があるか整理しやすくなり、うっかり後から上書きしてしまったなどの外からの影響を防ぐことができます。
(余談:PugのMixinをコンポーネントごとに分け、これもファイル単位にしてSassと対応させるとさらにGoodです。)
・過剰なネストを避ける
ネストが深くなればなるほどあっという間にCSSは複雑怪奇になります。ネストして書くことで記述量も少なく簡単に書くことができますが、ネストを1階層にとどめることによってコード上の関連性が見やすくなります。
BEM+RSCSS=BEV
さて、先ほどRSCSSはBEMをもっと良くするアイデアだと述べました。
そこで私はBEMの基本は抑えつつ、そこにRSCSSを取り入れたものを使っています。
だいたいこんな感じです。↓
<div class="component-block">
<div class="component-block__element"></div>
<div class="second-component-block component-block__child">
<div class="second-component-block__element"></div>
</div>
</div>
<div class="component-block -variant">
<div class="component-block__element"></div>
</div>
.component-block {
background: red;
&__element {
padding: 16px;
}
&__child {
margin-top: 24px;
}
&.-variant {
background: blue;
}
// elementにvariantがついた場合
&__element.-variant {
// ここでもネストは1階層
}
}
本家からの変更点、混ぜたところは以下です。
・Elementsは子セレクタ(>)で指定せずBEMのelementそのまま。(子セレクタはHTMLの変更に弱いため)
・BEMのModifierをRSCSSのVariantに置き換え。
・BEMのblockの命名規則はRSCSSのComponentsに則る。
・コンポーネントに親子関係が発生するときは、子コンポーネントを親のElementとして扱い、Layoutの定義は親のElementのプロパティで行う。
そのほかはBEMとRSCSSに則ります。
BEMのModifierをVariantに変更しているため、「BEV」と呼んでいます。
Tailwind CSS
BEMもRSCSSもコンポーネント指向の手法でしたが、Tailwind CSSはユーティリティファーストの手法で、フレームワークとしても提供されています。
作者の意図については、こちらの翻訳記事に詳しく書かれています。
Tailwindはコンポーネントではなく、スタイルそのもののクラスを当てていく書き方になります。そのため、デザインシステムと非常に相性が良いです。
具体的にはこんな感じです。
<div class="p-16 bg-white text-black"></div>
スタイルそのもののクラスを当てることで、デザインシステムを見たまま適用させることができます。
つまり、新規のコンポーネントclassを作りそこに個別にスタイルを当てていくのではなく、すでに用意されているスタイルと1対1のclassを当てていくのでCSSの記述量がかなり減ります。
またclass命名=当たっているスタイルなので、スタイルを変更したい場合にはCSSを確認しにいかなくともclassを書き換えるだけで良くなります。
しかし複数のスタイルを当てていけばいくほど、classの数は多くなっていきます。
<div class="fixed inset-0 flex items-end justify-center px-4 py-6 pointer-events-none sm:p-6 sm:items-start sm:justify-end"></div>
最初にこれを見たとき、私はウッとなりました。長い・・・見にくい・・・
BEMのような記述に慣れている人からすると、この書き方に慣れる必要はあるかもしれません。(「慣れ」の問題はどこにでも起こりうることです)
ただしコーディングルールで記述の順番を決めておく(例えばポジション関連は最初に書く、など)ことで、カオスになることは防げると思います。
もう一つの懸念点は、例えば同じ見た目のものに対していくつものクラスをまた書かなければいけないのか、という点です。
これに対してはコンポーネントが解決してくれます。
一部の機能本位のCSS擁護派と私とで少し意見が異なる点のひとつは、ユーティリティだけでなにかを構築すべきではないと思うということです。
記事内で作者の方が述べているように、Tailwindはけしてユーティリティクラスのみで構成するものではなく、コンポーネントと併用すべきとされています。
私がCSSユーティリティファーストと呼んでいるのは、できる限りはすべてユーティリティから構築し、繰り返しのパターンのみを抽出するようにしているからです。
このように重複するユーティリティはフレームワークでコンポーネントとして切り出しても良いですし、フレームワークを使用していない場合は @applyディレクティブ を使用することによってユーティリティクラスをまとめた新しいクラスを作成することもできます。
.action-btn {
@apply text-base font-medium rounded-lg p-3;
}
またコンポーネントと併用することで、デザインシステムで定義されているもののみユーティリティクラスで制御し、特殊なコンポーネント独自のスタイルやインタラクションはコンポーネントクラスで制御することができるので、どこが共通化されているのか切り分けが容易になります。
BEM+RSCSS+Tailwind=?
BEM+RSCSS最高!としばらく使っていたのですが、最近Tailwindに出会い、これ組み合わせたらもっと最高なのでは?と思うようになりました。
BEM+RSCSS+Tailwindはまだ試行回数が少ないので、また問題点が出てくることもあるかもしれませんが、今使っていきたいMyブームです。
昨今のフレームワークとの兼ね合いや、プロジェクトによってもマッチするCSS設計手法は変わってくると思います。
Webを取り巻く状況も常に変わっていきますし、考え続けることでより良くなっていくと思うので、ベストを模索してMyブームもアップデートを続けていきたいです。
この記事が気に入ったらサポートをしてみませんか?