CHROMA

世の中の "当たり前" を確認する

SMACSS に BEM を取り入れよう

f:id:thleap:20131215164631p:plain

BEM Advent Calendar 2013 の 15日目の記事です。
明日は @kubosho_ さん。

なぜ SMACSS ? なぜ BEM ?

  • SMACSS は CSS をより体系立て、構造化させることで開発者の制作とメンテナンスを容易にするテクニックとして、 Jonathan Snook によって提唱されました。
  • BEM ( MindBEMding ) は CSS のクラス名を明快にし、開発者本人だけでなく、誰が見てもクラス名から意味が読み取られるように、他のクラスとの識別をより容易にするためにロシアの Yandex という会社によって作られました。

SMACSS と BEM 、そして Nicole Sullivan が提唱している OOCSS というものがありますが、これらはどれも CSS に構造を持たせて(プログラムのオブジェクト指向のように)設計しなさいということが書かれています。
「なぜ構造を持たせて設計する必要があるのか?」ということについては、一言で言えば 制作と制作後のメンテナンスを容易にするため です。 CSS ファイルが作った本人にしかさわれないということや、作った本人にもさわれない.. ということがないようにするためです。

また、先日の HTML5 CONFERENCE 2013 の "モダンなCSS設計パターンを考える" というセッションの中で、 CSS の設計を考える上でのゴールは次のように言われていました:

  • 予測しやすい
  • 再利用しやすい
  • 保守しやすい
  • 拡張しやすい

各手法と共に、CSS を書く時はこの 4つを常に意識しておく必要があります。意識することで今でている手法よりもより良い手法が頭に浮かんでくるかもしれません。

SMACSS のモジュールカテゴリーで BEM をつかう

SMACSS ではカテゴリー毎には上手く分かれているように思いますが、カテゴリー内での各モジュールの分離という点については少し弱さが残っているように思います。

これは特に( SMACSS のモジュールカテゴリー内で )モジュールを作るときに感じていています(僕の書き方が特別悪いかも)。 以下のコードはサンプルになりますが、次のようなケースでモジュールの区別が付きづらくて困ることがあります:

.panel {
  ...
}

.panel-full {
  ...
}

.panel-header {
  ...
}

.panel-header-border {
  ...
}

.panel-header-heading {
  ...
}

.panel-header-point {
  ...
}

.panel-header-point-stars {
  ...
}

.panel-body {
  ...
}

.panel-body-table {
  ...
}

.panel-body-lists {
  ...
}

.panel-footer {
  ...
}

.panel-footer-button {
  ...
}

.panel-footer-note {
  ...
}

.panel-footer-note-attention {
  ...
}

panel-fullpanel-header-borderpanel-footer-note-attention は一部状況に応じてスタイルを変更するクラスですが、それがこのクラス名からは判断がつきません。
また、panel-header-pointpanel-header-point-stars に親子関係はなく、兄弟関係にあたるものになりますが、それもこのコードからは判断できません。
これらはクラス内にプロパティが書いてあれば、そこから判断できるものもあるかと思いますが、誰しもがプロパティまで細かく見て判断してくれるとは限りません。

この問題については、 BEM の命名規則を使い、クラス名を Block (アプリケーションの構成要素)、 Element ( Block の構成要素)、 Modifire (元となる Block や Element で一部スタイルの変更に使うもの)で分け、これらの各連結方法には Element は名前の前にアンダースコア 2つ( __ )、Modifire は名前の前にハイフン 2つ( -- )繋ぎといったルールを持たせることでモジュール間の区別をつけることで解決できます。
(このへんの詳細については BEM とは という記事で書きました)

BEM の命名規則を適用することで、上記のようなケースはこのようになります:

.panel {
  ...
}

.panel--full {
  ...
}

.panel__header {
  ...
}

.panel__header--border {
  ...
}

.panel__header__heading {
  ...
}

.panel__header__point {
  ...
}

.panel__header__point-stars {
  ...
}

.panel__body {
  ...
}

.panel__body__table {
  ...
}

.panel_body__lists {
  ...
}

.panel__footer {
  ...
}

.panel__footer__button {
  ...
}

.panel__footer__note {
  ...
}

.panel__footer__note--attention {
  ...
}

これで少しは一部のスタイルの変更に使うクラス、各クラス間の関係に区別が付くようになったのではないでしょうか。

今年いろんな CSS 設計の手法が出て、これから

去年くらいから OOCSS 、SMACSS と BEM と、CSS の設計を行う上での手法がいくつか出てきており、これらを僕も少しずつ使うようになってきました。
各手法がなんの目的で作られたのかというのを理解し、そしてそこから学んだ良いところ・悪いところを判断していきながら 1つの手法に縛られること無く、自分で納得のできる CSS (自分ルールではなく周りにも認められる CSS )をいつか.. 書きたいと思っています。

そのためには こちら にも書いてる通り、新しい手法に目を向けるだけでなく、プログラムの本質を学ぶ必要があると思いました。CSS はプロパティを覚えてさえいれば構造などを考える事無く書けてしまうからこそ、逆に構造を強く意識しておく必要があると感じています。

SCSS などのメタ言語や、今回紹介した CSS 設計の手法はプログラムの考え方からきています。
これらを学ぶと共に、または前に、RubyJavaScript といった他のプログラム言語を理解するのも 1つの手かもしれませんね。

参考

BEM が使われているプロジェクト

definitions.md - juno / bem-methodology-ja で紹介されていたものの中からいくつか。

日本でも既に BEM を使って作られたブログがある!

BEMとOOCSS原則に基づいた CSS の設計手法。

僕が書いたブログ