BEMによるコンポーネント設計


## BEMとは

再利用可能なコンポーネント単位でCSS設計を行う、CSS設計手法です。

## コンポーネントの考え方

design|css設計
---|---
![design.png](https://qiita-image-store.s3.amazonaws.com/0/87773/961dbd5e-9517-804d-9b1c-5cda9f63783b.png "design.png")|![bem.png](https://qiita-image-store.s3.amazonaws.com/0/87773/33fc04ff-726d-fb25-0e37-11c4546819fd.png "bem.png")

まず、このデザインは主に以下のコンポーネントで構成されています。コンポーネントの切り方は人それぞれですが、最終的にはレゴのブロックのように、コンポーネントを組み合わせてWebサイトを実装します。したがって、再利用可能な単位でコンポーネントを分割するのが推奨されます。

コンポーネント|イメージ
---|---
ヘッダー|![スクリーンショット 2017-10-07 18.51.30.png](https://qiita-image-store.s3.amazonaws.com/0/87773/74e4a83f-2865-2424-29ef-e081265065c4.png "スクリーンショット 2017-10-07 18.51.30.png")
ナビゲーション|![スクリーンショット 2017-10-07 18.51.49.png](https://qiita-image-store.s3.amazonaws.com/0/87773/8eb7e22b-12ff-54c1-4c10-5dbbea5c8b78.png "スクリーンショット 2017-10-07 18.51.49.png")
見出し|![スクリーンショット 2017-10-07 18.53.06.png](https://qiita-image-store.s3.amazonaws.com/0/87773/65014741-5f6e-43b5-dd85-9665c3704af5.png "スクリーンショット 2017-10-07 18.53.06.png")
文章|![スクリーンショット 2017-10-07 18.53.55.png](https://qiita-image-store.s3.amazonaws.com/0/87773/e4b62ca2-6c70-3f7c-cc7c-aab5beb55e61.png "スクリーンショット 2017-10-07 18.53.55.png")
順序リスト|![スクリーンショット 2017-10-07 18.54.24.png](https://qiita-image-store.s3.amazonaws.com/0/87773/d5a7771f-2ba4-f0da-4954-c9395a78f36a.png "スクリーンショット 2017-10-07 18.54.24.png")
リスト|![スクリーンショット 2017-10-07 18.55.01.png](https://qiita-image-store.s3.amazonaws.com/0/87773/e0d232f8-bab8-702c-8c40-d278aa7883ad.png "スクリーンショット 2017-10-07 18.55.01.png")
テーブル|![スクリーンショット 2017-10-07 18.55.18.png](https://qiita-image-store.s3.amazonaws.com/0/87773/65a7db19-0b8d-ad8b-a32e-aaa8ce9b4708.png "スクリーンショット 2017-10-07 18.55.18.png")
カード|![スクリーンショット 2017-10-07 18.56.36.png](https://qiita-image-store.s3.amazonaws.com/0/87773/1141a59b-7a77-4f79-8d30-a5bf9d7342c2.png "スクリーンショット 2017-10-07 18.56.36.png")
ボタン|![スクリーンショット 2017-10-07 19.00.08.png](https://qiita-image-store.s3.amazonaws.com/0/87773/fc913117-d617-5617-750a-b7ec9e2cf9f0.png "スクリーンショット 2017-10-07 19.00.08.png")
定義リスト|![スクリーンショット 2017-10-07 18.59.33.png](https://qiita-image-store.s3.amazonaws.com/0/87773/60b95f26-472b-6684-e212-4f89c2989a84.png "スクリーンショット 2017-10-07 18.59.33.png")
フッター|![スクリーンショット 2017-10-07 19.00.28.png](https://qiita-image-store.s3.amazonaws.com/0/87773/9cbffdc9-b1ad-ac2d-af80-3b184bb196ad.png "スクリーンショット 2017-10-07 19.00.28.png")

## BEMの命名規則

BEMには厳格なCSS命名規則があります。これに従わないと、どこまでがコンポーネントで、どこまでがコンポーネントの中の要素なのかが分からなくなります。

## 単語は `-` 一つで区切る

```bem.css
.hdg-main {
  ...
}
```

- `hdgMain` や、`hdg_main` はNGです

## Block と Element

BEMではコンポーネントを `block` コンポーネントの子供を `element` と呼びます。コンポーネントの子供（element）は、コンポーネント名(block)に、アンダースコア２つをつけて表現します。

```bem.css
.header {
  ...
}
.header__logo {
  ...
}
```

これにより、ロゴはヘッダーの子供であるということが分かります。なお、elementはあくまでblockに依存しているblockの子供のなので、elementが単体で他の場所で使い回されることはありませんし、そのような使い方はNGです。また、elementには子供を持たせることはできないため、elementの子供に位置するclassであっても、あくまでblockの子供として命名してください。

```bad-bem.css
.header {
  ...
}
.header__logo {
  ...
}
/* element の子供はNG。この場合 .header__logo-text などとする */
.header__logo__text {
  ...
}
```

### Modifier

色が違うだけなど微妙に見た目が違うコンポーネントは、modifier という命名規則に沿ってデザインします。例えば色以外見た目が全く同じな緑のボタンと赤いボタンがデザインとして存在するとき、まずは緑のボタンをデザインし、それに対し modifier として赤いスタイルを作成する方が効率的です。modifier は元となるclassに `--` をつけ、modifier名を追加します。

```bem-modifier.css
.btn {
  color: green;
  font-size: 12px;
  padding: 16px;
  display: inline-block;
}
.btn--error {
  color: red;
}
```

```bem-modifier.html
<button class="btn">緑のボタン</button>
<button class="btn btn--error">赤のボタン</button>
```

ここで注意したいのが、modifierはあくまで元の素材に対するトッピングなので、必ず元となるスタイルとセットで指定し、元となるスタイルに装飾が当たるようにする必要があります。したがって下記の実装はNGです。

```bad-bem-modifier.html
<button class="btn">緑のボタン</button>
<button class="btn--error">赤のボタン</button>
```

また、`-` が一つの場合は単語区切りで、 `-` が二つの場合は modifier なので混合しないようにしましょう。modifierはblock に対しても element に対しても追加することができます。

## レイアウトとコンポーネントの区別

多くの場合、BEMはあくまでコンポーネントの設計を担うため、コンポーネントの配置（レイアウト）とは切り離して考えるべきです。例えば、カードが下記のようなデザインがあったとします。

![スクリーンショット 2017-10-07 19.26.58.png](https://qiita-image-store.s3.amazonaws.com/0/87773/0d0d12f7-4103-ddc5-638d-ebd9babb5135.png "スクリーンショット 2017-10-07 19.26.58.png")

この際、カード単体のコンポーネント設計ではなく、二つ並びのカードとしてコンポーネントを設計してしまっていた場合（つまり配置、レイアウトについてもコンポーネントに含めてしまった場合）、その下で登場する黒いエリアにおいて、汎用的に使いまわすことができなくなってしまいます。

あくまでそのパーツの見た目を設計し、それがどこでどのように配置されるかというレイアウトは設計に含めない方が、汎用的なコンポーネントになります。