クリスマスなのでBEMを紹介する

[CSS Advent Calendar 2014](http://qiita.com/advent-calendar/2014/css)も最終日となりました。最近なにかと話題のBEMについて書いていきたいと思います。

# BEMとは

Block Element Modifierの略で、Webサイトのコンポーネント化のための厳密なclass命名規則です。

# 手法

BEMの手法はそれほど複雑ではありません。

世の中のWebサイトは、ヘッダ、検索バー、記事など、多くの要素によって構成されています。これらの大きな要素をBlockと呼びます。

それぞれのBlock、例えばここでは検索バーについて注目すると、検索バーは検索ボックスや検索ボタンなど、更に幾つかの要素が組み合わさって出来ていることがわかります。これをElementと呼びます。

ElementやBlcokは、既存のものとほぼ同じであるものの、少しだけ変化させたようなものが必要になることがあります。これをModifierと呼びます。

BEMの命名規則では、このBlock Element Modifierを、block__element--modifierのようにして表します。ElementやModifierは省略可能ですが、blockは省略できません。

また、単語の区切りにはハイフンを一つ使います。

~~~html
<article>
  <h1>Article</h1>
  <div class=box>
    <h2 class=box__title--first>Box</h2>
  </div>
  <div class=box>
    <h2 class=box__title>Box</h2>
  </div>
</article>
~~~

また、「ヘッダ-メニューグループ-メニュー-項目」のように、Block Element Modifierでは足りないことがあるかもしれません。その場合は、以下のようにBlockをネストさせるのが良いと思います。

~~~html
<header class=header>
  <ul class=menu-groupe>
    <li>
      <nav class=menu>
        <ul>
          <li><a href=top class=menu__item--active>Top</a></li>
          <li><a href=page class=menu__item>Page</a></li>
        </ul>
      </nav>
    </li>
  </ul>
</header>
~~~

# カスタマイズ

BEMではアンダーバーやハイフンを2つ重ねるため、慣れていない人には気持ち悪く感じる人も多いようです。しかし、必ずこうしなければならないというわけではありません。

例えば、単語の区切りにハイフンを使用せず、キャメルケースを使用すれば、block_element-modifierのようにすることも可能です。

このように、重要なのは記法を統一することであり、アンダーバー二つやハイフン二つという形式に固執する必要はありません。

ただし、この独特な記法によってBEMであるということがわかりやすくなるというメリットもあるため、よほど気持ち悪く感じるということでなければ、そのまま使用すれば良いのではないかと思います。

# BEMが解決すること

## 混沌とした命名規則

現在、CSSの命名規則に王道は存在しません。それぞれのエンジニアが独自の命名規則を採用しているのが現状ではないでしょうか。

そのため、新しくプロジェクトに参加したメンバーがその設計手法を理解できないことも多々でした。

BEMという統一された手法を採用することで、誰もが設計を理解しやすく、また後述の通りやや独特な命名規則であるため、BEMが採用されていることがわかりやすいという利点もあります。

## HTML構造への依存

例えば次のようなページがあったとします。

~~~ css
.box h2 { color: red }
~~~

~~~html
<article>
  <h1>Article</h1>
  <div class=box>
    <h2>Box</h2>
  </div>
</article>
~~~

何らかの事情で次のようにタグを変更したとしましょう。

~~~html
<article>
  <h1>Article</h1>
  <div class=box>
    <h1>Box</h1>
  </div>
</article>
~~~

この変更によって、スタイルが崩れてしまいます。このように、HTMLの変更によってスタイルが崩れてしまうことが多々ありました。

以下のように、BEMを採用すればスタイルが崩れることはありません。

~~~ css
.box .box__title { color: red }
~~~

~~~html
<article>
  <h1>Article</h1>
  <div class=box>
    <h1 class=box__title>Box</h1>
  </div>
</article>
~~~

## コンポーネントの再利用

HTML構造への依存と似たことではありますが、これまでの場合、コンポーネントを再利用しようとしてもレイアウトが崩れることがよくありました。BEMを採用すれば、HTML構造に依存しないため、再利用が簡単にできます。

# その他思うこと
## どこまで厳密にするか

BEMではHTMLにCSSが依存しないようにするため、基本的に要素型セレクタを使用するべきではありません。ただし、それではあまりに冗長になってしまう箇所があります。

たとえば、ulの子はli以外には有り得ません。また、将来のHTMLでもおそらくこれは変わらないでしょう。このような場合、要素型セレクタを使用しても良いのではないでしょうか。

## 既存のCSSフレームワークの組み合わせ

BEMとBootstrapのような既存のフレームワークを組み合わせると、以下のように非常に見通しが悪くなってしまいます。

~~~html
<article>
  <h1>Article</h1>
  <div class="box panel panel-default">
    <h1 class="box__title panel-body">Box</h1>
  </div>
</article>
~~~

bootstrapであれば、bootstrap-sass-officialのように、各フレームワークはlessやsassで使用できる場合が多いです。このようなものを使用して、mixinとしてBEMのクラスの中に内包してしまうのが良いと思います。

ない場合は…諦めましょう。誰かいい方法知りませんか。

# まとめ

BEMは独特で便利な手法です。まだまだ探求され尽くしていないので、色々と模索すると良いと思います。

# 参考

- [BEM. Block, Element, Modifier](http://bem.info/)
- [BEMによるフロントエンドの設計 - 基本概念とルール | CodeGrid](https://app.codegrid.net/entry/bem-basic-1)
- [BEMという命名規則とSass 3.3の新しい記法 - アインシュタインの電話番号](http://blog.ruedap.com/2013/10/29/block-element-modifier)