CSSのModifier系クラスを簡潔に

一言で

BEMでいうModifierの役割にあたるクラスって、名前にコンポーネント名を含める必要ないのでは?

CSSクラス名の設計に関する一案

とりあえず CSS in JS や Web components 系の解決策を除外した上で、 ネームスペースがない現状のCSSの世界でメンテナブルなクラス名をつけていこうとする場合、 どうしてもBEMのようにコンポーネント名をベースにして一意性を確保していく形になる。 それはしょうがないとして、問題はHTMLでのクラス記述が長くなりがちになる事。 BEMでいうと、特にBlock/ElementとModifierをセットで使う場合は、コンポーネント名を何度も記述しないといけない。 しかし、その重複は本当に必要なのだろうか?

<div class="block block--size-big block--shadow-yes">
  <span class="block__elem"></span>
  <!-- ... -->
</div>

SMACSSにおけるStateクラスのネーミング

例えばSMACSSというBEMとはまた別の設計案を見てみると、 そこにはStateと分類されるクラスがあり、ごくシンプルなネーミングルールを持っている。 Stateクラスは主に一時的な状態を表現するクラスを指していて、それらはis-erroris-hiddenなど、is-xxxという形式で表現される。

このネーミングは見た目にも役割がわかりやすいし、何より簡潔に記述できる点で優れている。 しかし名前が簡潔なのはもちろん、コンポーネント名が含まれていないからだ。これでは名前の一意性が保証されないので、 例えば別々のCSSファイル内でis-hiddenというクラスにスタイルを定義していた場合、 当然意図しないスタイルの衝突が起こりうる。

だが逆に言えば、「is-xxxというクラスには単体でスタイルを適用しない」というルールさえ徹底すれば、 そのような事態を恐れる事なくこの簡潔なクラス名を使っていける、という事でもある。 つまりStateクラスに関しては、.tab.is-active.menu.is-closedのように、常に他のクラスとの組み合わせでのみスタイルを定義すればいい。 is-のように動詞始まりである事で「他のクラスと組み合わせて使うもの」というルールは暗に示せているし、 徹底する事はそれほど難しくなさそうに思える。

であれば、この方法は何も一時的な状態変更に限らず、BEMのModifierのようなクラスでも使えるのではないだろうか?

バリエーションクラス

あるコンポーネントと基本は同じだが少し異なるデザインを使いたい場合 (Modifier)、 あるいはユーザからの入力などのイベントに応じて一時的にそのコンポーネントの状態を変えたい場合 (State)、 どちらもis-xxxというクラス名で表現すればいい。これらは「バリエーション」という呼び名で統一できると思う。 固定的なものにせよ一時的なものにせよ、 もととなるコンポーネントの一部のスタイルを上書きする目的で使うクラスはバリエーションクラスと呼べる。 そして、バリエーションクラスは常に他のクラスと組み合わせたものに対してスタイルを定義するというルールにする。 そうする事で、組み合わせるクラス名がバリエーションクラスにおけるネームスペースのような役割を果たす。

これならHTMLでベースとなるクラス名とバリエーションクラスを組み合わせる時も、 コンポーネント名を何度も書かずに済むようになる。

<div class="block is-large has-shadow">
  <span class="block__elem"></span>
  <!-- ... -->
</div>

is-に限定する必要はない

上記のように、バリエーションクラスの表現力を増すためにis-以外のプレフィックスを用意してもいいかもしれない。 has-item, are-hidden, of-usersなど、使えそうな動詞・助動詞は割とありそう。

一時的である事を強調したい場合

バリエーションの中でも、一時的な状態を表すクラスと固定的なバリエーションをちゃんと区別したい場合、 前者にはnow-というプレフィックスをつけるのも悪くない (now-active, now-loading, etc)。 これなら一目で一時的な状態である事がわかる。 ただ何を持って「一時的」とするかは決めづらい場合もありそうだから、それほどこだわる必要はない気もする。

まとめ

今回思いついたルールをまとめると以下のようになる。

  • トップレベルのクラス名は (now以外の) 名詞始まりにする
  • コンポーネントのバリエーションはis-xxxといった受動態で表現する
  • バリエーションをよりわかりやすくするために、now-xxxhas-xxxといったプレフィックスを使うのもあり

上記はあくまでルールにとどまるが、やろうとすればCSSを静的に解析して、 バリエーションクラス単体にスタイルが定義されていないかをチェックする事もできるはず。

以上、ふと思いついた案をまとめてみたけど、まだ実際にこの方法でCSSを管理してみた事はないので、 どこかで試してみたい。