HTML5Experts.jp

抽象化を避けるCSS設計方法論「Enduring CSS」 第1回

連載: Enduring CSS (1)

本連載では、Enduring CSSというCSS設計方法論を紹介します。Enduring CSSは、Ben Frain氏の著書で、末永く破綻させずにサイトのCSSを設計するにはどうすればよいか。その方法論をまとめたものです。電子書籍でも販売していますが、Webサイトで全ての内容が公開されていますので、無料で全内容を確認可能です。

CSS設計方法論(CSS methodology)と言うと、OOCSS、BEM、SMACSSの3つが著名なものと言えるのではないでしょうか。

特にBEMは、フロントエンド界隈でクラスの命名規則のデファクトスタンダードになったとも言ってしまっていい気がします。このEnduring CSS(以降ECSS)は、これらのCSS設計方法論と比較すると、知名度は低く、事細かにドキュメントが用意されているわけではありません。

しかしながら、ECSSの内容は筆者Takazudoにとって目からウロコであり、CSS設計に対する考え方をかなり改めさせられることとなりました。ECSSは、そこまでカッチリとしたルールではありません。サイトを長生きさせるにはどうすればいいかというヒント集のようなものと思って読むとよいと思います。

そんなEnduring CSSというCSS設計方法論を、ざっくりと紹介していきます。

ECSSの特徴

多くのCSS設計方法論では、ページを構成するUIをモジュールなどと呼ばれる単位に分け、管理するところから始めます。ECSSでもその考え方は同じです。この「モジュール」は、BlockだとかObjectだとかComponentだとか、いろいろな呼ばれ方をしますが、ECSSではこれをModuleと呼びます。

ECSSは、Module及びそのModuleの中身がどう構成されるかという考え方について、BEMを参考にしています。そこにNamespace(名前空間)や、Componentという概念を付け足したのがECSSの考え方になります。

抽象化を避けるECSS

ECSSでは、抽象化を避け、なるべく「分けて」管理することで運用の負荷を下げるというアプローチを取ります。

例えばOOCSSでは、ページを構成するUIをレゴの組み合わせで構成すると例えています。複雑なUIも単純なレゴをうまく組み合わせで構成し、新しいページを作る場合でも、既存のObjectで使えそうなものがあったらその組み合わせで構成し、足りないものは新しく作るという、HTMLとCSSの再利用を推し進めた考え方です。その結果、CSSを書く量が減るため、CSSの容量を減らすことができると。

そして、一つ一つのレゴをObjectと呼び、このObjectの変化のパターンをバリエーションをSkinという概念で表現し、オブジェクト思考における継承の考えを取り込んだ、かなりCSS的にミニマムな設計を指向しています。UIパーツをObjectで抽象化して考えるという具合です。

ECSSは、OOCSSのこのアプローチとは真逆と言ってよい考え方をします。ページを構成するUIパーツをモジュール化して管理するという点については同様ですが、多くの機能で汎用的に使用するModuleの存在をあまり良しとしません。同じような見栄えのUIパーツが登場したとしても、基本的にそれは別のものであると定義します。

そう聞くと疑問に思うことでしょう。その考えでコードを書いていったら、おなじCSSを何度もコピペすることになってしまうのでは?と。

CSSの重複を許すECSS

ECSSはそのようにCSSを重複して書くことを良しとします。

そのように考える大きな目的は、複雑化の回避です。幾つものObjectが組み合わされ、Skinでそれぞれが拡張された状態のコード。これを編集するのは、時に大変な作業になりえます。何が大変かというと、他所での影響を考慮しなければならないからです。

既に書いてあるCSSのルールセットを変更した場合、他のどこかで問題が発生しないと言い切れるでしょうか。小さなサイトであればそれは可能でしょう。しかし、複数のデベロッパーがコードをいじるような環境では、それを制御するのは困難を極めます。

そのように複雑な構造を一度作ってしまったら、ゆくゆくはコードを編集することが不可能になる。そしてCSSは破綻する。CSS容量を増やしてしまったとしても、「分ける」ことにより、これを避けるメリットのほうが遥かに大きいと考えるのがECSSです。CSSの容量増加は、gzipすれば大した差にはならないとECSSは考えています。

これは筆者Takazudoのイメージですが、OOCSSが目指すのが一つの高い塔であれば、ECSSが目指しているのはビル街です。

ECSSには、自身が大きなWebアプリケーションのCSS設計のため、合理的なアプローチが必要で考えたものであると書かれています。また、どのようなサイトにも適した考え方であると言うわけではないということも書かれています。このことは予め理解しておく必要があります。

ECSSにおけるModule内の構成

まずはECSSにおいて、Module及びその内容をどのように考えているのかを紹介します。基本的な考え方はBEMと同じなので、以下、BEMと比較する形で説明します。

例えば、こんなタブUIの構造を例に考えてみます。

BEMにおいて、このUIのタブ部分をBlockであると定義すると、

タブUI全体がBEMにおいてのBlock。これはECSSではModuleと呼びます。

そして例えば、一つ一つのタブがBEMにおいてのElement。これはECSSではChildNodeと呼びます。

状態により変化するようなパーツは、BEMではModifierというフラグを付加することで表現します。これをECSSではvariantと呼びます。

このあたりは、BEMを理解しているのであれば、呼び方が変わっているぐらいの差に過ぎません。

BEMのクラス命名規則

BEMでは、このように考えた上で、各要素に命名規則に沿ったクラスを付加し、単純なクラスセレクタでルールセットを書いていきますが、これについてもECSSは同様です。

BEMにおけるクラスの命名規則は以下です。

block__element--modifier

例えばこのタブUIのコードだと、以下のようになるかもしれません。

<ul class="tab">
  <li class="tab__item"><button>One</button></li>
  <li class="tab__item tab__item--active"><button>Two</button></li>
  <li class="tab__item"><button>Three</button></li>
  <li class="tab__item"><button>Four</button></li>
</ul>

ECSSのクラス命名規則

これに対し、ECSSにおけるクラスの命名規則は以下です。

namespace-Module_ChildNode-variant

namespaceというのは名前空間を意味しますが、これは追って解説します。他はBEMの名前が置き換わったぐらいと考えておいてよいです。

<ul class="tp-Tab">
  <li class="tp-Tab_Item"><button>One</button></li>
  <li class="tp-Tab_Item tp-Tab_Item-active"><button>Two</button></li>
  <li class="tp-Tab_Item"><button>Three</button></li>
  <li class="tp-Tab_Item"><button>Four</button></li>
</ul>

ECSS著者はBEMの区切り文字が好みではないらしく、アンダースコアとハイフンで区切りを表現します。

ほか、ModuleとChildNodeはアッパーキャメルケースで記述します。これは、多くのプログラミング言語で、クラスの宣言は大文字からはじめ、そこからインスタンスを作成することになぞらえ、HTMLにおけるこのクラス属性に指定するこの文字列は、具体的なUIを表現するための雛形であるという考えのもと、アッパーキャメルケースで記述することにしたそうです。 (筆者Takazudo的にはけっこうナルホドと思いました)

Component

ECSSでは、Module内で登場するある程度の大きさを持ったUIの塊を、Componentとして定義することにしています。

例えば、ヘッダーのModule内でプルダウンメニューが登場したら、そのプルダウンをComponentとして扱うというような具合です。その場合は、上記クラス命名規則は以下ように、ModuleがComponent名に置き換わった形になります。

namespace-Component_ChildNode-variant

どのようにComponentとしてまとめるかは各々が判断して設計する部分で、明確な切り分け基準があるわけはありません。Componentは、Moduleの大きさが大きくなった場合、コードの可読性やJavaScriptとして操作するまとまりの区切りをつけるために用意されるものと考えておいて良さそうです。

Moduleの粒度

ECSSには、Moduleは以下であると書かれています。

a module is the widest, visually identifiable, individual section of functionality.

「Moduleは、視覚的に認識できる個別の機能領域のもっとも大きな区分である」とでも訳せばよいのでしょうか。この定義からは、あまり小さい単位のUIをModuleであると定義しないような印象を受けます。

具体的なModuleの例

具体的にはどうModuleを考えればよいのか。丁度ECSSのWebサイト自体がECSSで書かれているので、そのクラス名から、Moduleの粒度がどのようなものかを見てみました。

※2017年1月時点でのWebサイトのコードを参照しています

ページの中ほどにある、ECSSの利点を述べたBenefitsというModuleです。

このようなUIをHTMLとCSSで作る場合、例えばBEMであればどのようにBlockとElementを構成するでしょうか。

明確な決まりは当然ありませんが、例えば上部にある見出し部分、アイコン一つ一つ、アイコン直下にあるラベルなどを個別のBlockとして切り出し、Blockの入れ子により構成されると考えることもできます。

他でもそのBlockが使えそうだなと、そのように細かくBlock分けをしてもよさそうですが、実際のECSSのWebサイトでは、以下のようにクラス名が振られていました。

以下は、上記で青で囲んだhome-Benefits_Unitの内容です。

このクラス名から判断されることは、このBenefitsとういうModuleは、このModule内に別のModuleやComponentが含まれておらず、中にある要素はすべてChildNodeとして構成されていることです。このことから、このModule内の要素は、このModuleの外側では一切使われないことが分かります。

また、このModuleの名称がBenefitsという、具体的な機能を示すという点についてもECSSらしいと言えそうです。もしこのModuleが他でも使用されることを想定するのであれば、IconTextSetなどという、汎用性を持った名前にしたほうが、後々都合が良いのではないでしょうか。

しかし、BenefitsというModule名からは、このModuleが、ECSSのBenefitsを表すためだけに使用されることが想起されます。

トップページにあるその他のModule群

ECSSのWebサイトトップページにおいて、他のUI群は、どのようにModule分けされているのかを見てみました。以下がその図になります。

各Module中のクラスも確認してみましたが、Module内に別のModuleがあるという、入れ子状態になっているModuleはありませんでした。また、各Module名称は、かなり具体的な単語になっているのも分かるのではないでしょうか。

単に一つのページの構成を例として挙げたにすぎませんが、このように、ECSSでは、Moduleを細かく分け、Moduleの入れ子で構成するような作りを避けることで、そのModuleがそれ自身で完結するようなModule分けを基本として考えています。同じような見栄えのUIが出ても、そのModuleの担う機能が別であれば、それは別のものとして扱います。

今回は、ECSSの考え方の概要と、Moduleについて解説しました。次回は、Namespaceとアセットの分離について解説します。