CSS設計手法のBEMをわかりやすく図解してみた

[Ateam cyma Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-cyma)、22日目です！
本日は株式会社エイチームでcymaのデザイナーをしている @ryo_cy が担当します。
今回はBEMというCSSの命名規則について、画像を使いながらわかりやすく説明していこうと思います！

##BEMとは？
BEMとはBlock、Element、Modifierという3つの要素の頭文字を取ったものになります。
命名の書き方は`block__element--modifier`とblockを先頭に記述します。
いきなりBlock、Element、Modifierと言われても何かよくわからないので、簡単に図にまとめてみました。
オレンジ色の枠で囲んでいる塊がBlock。
緑色の枠で囲んでいる要素がElement。
紫色で囲んでいる装飾部分がModifier。
以下の図を参考にしてBlock、Element、Modifierをより詳しく見ていきたいと思います。
![Component.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/d017c305-1405-a708-d643-1a6d46d215b4.png)



###Block
Blockは、要素をまとめているメイン、サイドバー、記事のリスト一覧など、大きな塊部分を示します。
先程の図でいうと以下のオレンジ色の部分になります。
![ComponentBlock.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/a8aa68ba-b6a5-4319-d6cc-330314134e45.png)
図のカード型コンテンツのフレームがBlockになります。
htmlとscssは以下のようになります。

```html:html
<div class="card">
</div>
```

```scss:scss
.card {
  border: 1px solid #ccc;
  padding: 20px;
}
```


###Element
Elementは、大きな塊の中に入っているタイトルやボタン、説明文などの細かな部品を示しています。
先程の図でいうと以下の緑色の部分になります。
![ComponentElement.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/0c89e346-a876-1180-a670-2e647d79ad0e.png)
図のカード型コンテンツのフレームに入っている各要素がElementになります。
htmlとscssは以下のようになります。

```html:html
<div class="card">
  <img class="card__image" src='a.jpg'>
  <h1 class="card__title">Title</h1>
  <p class="card__description">Lorem ipsum dolor ...</p>
  <a class="card__link">More</a>
</div>
```
クラス名を記載するときは以下のように`block__element`という規則で命名します。


```scss:scss
.card {
  border: 1px solid #ccc;
  padding: 20px;
  &__image {
    width: 100%;
  }
  &__title {
    font-size: 24px;
  }
  &__description {
    margin-top: 10px;
  }
  &__link {
    padding: 5px 30px;
    border: 1px solid #ccc;
  }
}
```

scssを記載するときはblockの中に`&__`をつけてElement名を記載します。

このように記載することで可読性が上がることと、コンパイル時に一つのクラスとしてcssが書き出されるため、その他のクラス名と重複することがありません。
例としてblockとtitleがCSSで出力されるときは以下のようになります。

```css:css
.card {
  border: 1px solid #ccc;
  padding: 20px;
}
.card__title {
  font-size: 24px;
}
```

###Modifier
Modifierは、ボタンやタイトルに色をつけたりと、各要素の装飾を行う際に使用します。
例えば、先程の図の右側コンテンツのボタンだけ青くしたいときなどに使用します。
下の図の紫色の部分がModifierです。
![ComponentModifier.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/c609fb51-8849-0c7c-9ce1-013e4228c743.png)

今回はボタンの色を変化させるので、ボタンのクラス名にModifierを追記します。
htmlとscssは以下のようになります。

```html:html
<div class="card">
  <img class="card__image" src='a.jpg'>
  <h1 class="card__title">Title</h1>
  <p class="card__description">Lorem ipsum dolor ...</p>
  <a class="card__link card__link--feature">More</a>
</div>
```
クラス名を記載するときは上記のように`block__element--modifier`という規則で命名します。

```scss:scss
.card {
  border: 1px solid #ccc;
  padding: 20px;
  &__image {
    width: 100%;
  }
  &__title {
    font-size: 24px;
  }
  &__description {
    margin-top: 10px;
  }
  &__link {
    padding: 5px 30px;
    border: 1px solid #ccc;
    &--feature {
      color: #fff;
      background: #55C0E1;
      border: 1px solid #55C0E1;
    }
  }
}
```
Modifierを記載するときはblockもしくはElementの階層中に`&--`をつけてModifier名を記載します。

##BEMの必要性
BEMについて簡単に説明しましたが、なぜBEMを使用する必要があるのでしょうか。
私が思うに、以下の点が挙げられます。
- 保守性が高くなる
- 可読性が上がる
- 再利用がしやすい

###保守性が高くなる
一番の理由とも言える部分です。
命名を規則化する事によって、保守性が高くなります。
BEMの規則上block要素が1つになるので、各要素のまとまりごとに管理することができ、要素の追加、削除を簡単に行うことができます。

![ComponentMaintainability.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/42629460-8876-34f6-15a7-ed003410f60d.png)


###可読性が上がる
BEMは`block__element--modifier`と、記述する規則があるため、SCSSで記載する際にネストが深くなりすぎず、すぐに読み解くことができます。

![ComponentReadability.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/d5d00be8-b1c1-1a33-851b-246c7738ea09.png)



###再利用がしやすい
BEMはblockを起点として1つの塊で使用しているため、ページ内でコンテンツを移動したときや、同じデザインでコンテンツを追加した際に、他のスタイルによる影響を受けないため再利用がしやすくなります。

![ComponentReuse.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/b3c64830-7cfa-aabe-7559-52ad62326122.png)


##BEMをもう少し実用的に使用してみる
簡単にBEMの書き方、特徴を説明してきたので、ここからはもう少し深掘りして見ていきたいと思います。
先程までの説明は、1つのブロックに対しての説明のみでしたので、複数の要素が関わる場合どのように考え、記述していくのかを把握することによってよりイメージがしやすくなると思います。
まずは以下のようなデザインがあったとします。

![ComponentMix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/5c852119-5161-fa5f-0f04-74dcf25c98d6.png)

このデザインを制作する場合、どのようにBlockとElementを分けていくのか最初に考えてみましょう。

###デザインをBlock、Elementに分けてみる
先程のデザインを分けてみると以下の3つのブロックに分けることができます。

![ComponentMixBEM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316574/cd51360d-3123-d32f-74fc-43bed6dd6814.png)

ポイントはボタンをBlockとして分けて考えているというところです。
Blockを分けて考えることによって、デザインパターンが違っても1度作ったソースコードを簡単に再利用することが可能になります。
それでは実際にソースを見ていきましょう。
(SCSSはセレクタの構造を見やすくするため、プロパティを簡素化しています。)

####HTML
```html:html
<div class="feature">
  <img class="feature__image" src="a.jpg">
  <div class="feature__copy">
    <h1 class="feature__title">Lorem ipsum dolor sit amet consectetuer adipiscing elit</h1>
    <p class="feature__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p>
    <a class="button" href="#">More</a>
  </div>
</div>

<ul class="cardList">
  <li class="cardList__item">
    <img class="cardList__image" src="b.jpg">
    <h2 class="cardList__title">Title</h2>
    <p class="cardList__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p>
    <a class="button" href="#">More</a>
  </li>
  <li class="cardList__item">
    <img class="cardList__image" src="c.jpg">
    <h2 class="cardList__title">Title</h2>
    <p class="cardList__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p>
    <a class="button" href="#">More</a>
  </li>
  <li class="cardList__item">
    <img class="cardList__image" src="d.jpg">
    <h2 class="cardList__title">Title</h2>
    <p class="cardList__description">Lorem ipsum dolor sit amet consectetuer adipiscing elit...</p>
    <a class="button" href="#">More</a>
  </li>
</ul>
```

####SCSS
```scss:scss
.feature {
  overflow: hidden;
  position: relative;
  &__image {
    float: right;
    width: 60%;
  }
  &__copy {
    position: absolute;
    top: 45px;
    left: 0;
  }
  &__title {
    font-size: 1.5rem;
  }
  &__description {
    font-size: 0.875rem;
    margin: 20px 0 40px;
  }
}

.cardList {
  display: flex;
  justify-content: space-between;
  &__item {
    width: 32%;
    border: 1px solid #ccc;
  }
  &__image {
    width: 100%;
  }
  &__title {
    font-size: 1.5rem;
  }
  &__description {
    font-size: 0.875rem;
    margin: 5px 0 20px;
  }
}

.button {
  padding: 5px 30px;
  border: 1px solid #ccc;
  border-radius: 5px;
}
```

再利用するデザイン要素がある場合は、上記のようにブロックを分けることでソースコードが理解しやすくなるとともに、管理も簡単になります。


##まとめ
BEMを使ったCSS設計の考え方や書き方について紹介させていただきました。
ごく一部のデザイン例を参考に記載しましたが、今回の内容を意識してサイトの構築をしてもらえれば管理のしやすい構造になっていくことでしょう！
最初のうちはどこでBlockを切り分けたらいいのか戸惑うかもしれませんが、デザイン全体を見たときに再利用できる部分を1つのまとまりとして認識していくことによって、徐々に慣れていくと思います。

今回は有名で考え方も簡単なBEMを紹介しましたが、CSS設計はBEMの他にもFLOCSS、SMACSS、OOCSSなど様々な手法があるので、サイトの規模やチームによって何を選択していくのかが、構築・運用していく上で大切になっていきます。
この記事が皆さんのCSS構築の参考になったら幸いです。

##おわりに
[Ateam cyma Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-cyma)の22日目、いかがでしたか？
23日目は@sakura523さんがゲームUIデザイナーからWebデザイナーにジョブチェンした話をしてくれますのでお楽しみに！

株式会社エイチームでは、一緒に働けるチャレンジ精神旺盛な仲間を募集しています。

エンジニアで興味を持った方はcymaの[Qiita Jobs](http://bit.ly/35E1I08)をご覧ください。

そのほかの職種は、[エイチームグループ採用サイト](http://bit.ly/2XQpd3q)をご覧ください。