【初学者向け】HTML/CSSでのclassの命名を考える　〜CSS設計（BEM）を学んでみよう〜

## はじめに
前回の記事「[フロントエンドエンジニア初学者の勉強リスト](https://qiita.com/nanarya/items/661ec10ff262c84424a6)」を書いたら思いの外たくさんの反響をいただけたのでちょっとやる気が出てきたフロントエンド初学者のnanaryaです。褒めて伸びるタイプです。
前回は全体の概要をさらった感じでしたが、今回はもうちょっと細かいところにフォーカスしたいと思います。
これを読めばわかる、というよりはこれを読めば「勉強の仕方がわかる」「調べるきっかけになる」というような内容ですのであしからず。
また、筆者自身フロントエンド初学者なので、間違っている点があるかもしれません。見つけたときは筆者ならびにこれから学ぶ初学者の方々のためにコメントで訂正いただければ幸いです。

### 今回のテーマは「classの命名」。
[前回の記事](https://qiita.com/nanarya/items/661ec10ff262c84424a6)でいうとCSSの中のCSS設計に分類されるお話です。
マークアップをしたことがある人はみんな一度は迷う、

```html:index.html
<div class="hoge"></div>
```
とか、

```css:style.css
.hoge { margin: 10px; }
```
とかのアレ（hoge部分）です。

この投稿は

- HTMLやCSSは書けるけれど、使いこなすためにもう一歩勉強したい
- classの命名にいつも迷う
- 現場で使われている技術や知識を身に付けたい

こんな人を対象に書いた、初学者向けの投稿です。
CSSの設計とBEMの非常に初歩的なところを解説していきたいと思います。

## CSS設計の初歩的なところを考えてみる
### classの命名っていうけどidじゃだめなの？
Qiitaを覗いてるみなさんには当たり前のことかもしれませんが、一応このあたりから書いていきたいと思います。
HTMLおよびCSSにはclassとidの２種類の名前の付け方がありまして、その名前が一致するものを紐づけてスタイルを書いていきます。
classとidの違いは、ページ内に複数存在できる(class)かできない(id)かです。
なので、正直idだけでページを作ることも可能です。が、一般的にはclassのみを使うことが多いです。
理由としては__classで書けばページ内で複数存在できるため、流用ができる__ことがもっとも大きいでしょう。
どうしてもidを使わないといけない場合（アンカーリンクを置くなど）や、JavaScriptの発火点とするとき以外はclassのみを使うのが常套手段のようです。

### classをうまく流用していこう
たとえばHTMLで`<div class="button">`というclassを作り、CSSで`.button { width: 200px; }`としておいて、ボタンを作るときにこの`button`というclassを使えば毎回CSSを書かなくてもwidthが200pxのボタンができますね。
この要領でうまく使いまわしていきたいんですが、あんまり細かく書き過ぎてもうまくいきません。

```css:style.css
.button {
  width: 200px;
  background-color: red;
}
```
例えばこれだと赤いボタンが簡単に作れますが、別の青いボタンを作りたいときに`button`というclassがそのままでは使えなくなってしまいます。
ここがマークアップの難しいところですね。
ではどのように`button`にはどこまでスタイルを書いて、どこからclassを分けて書いていけばいいのでしょう。
こういったことを考えるのが__CSS設計__です。
一口にCSS設計と言っても、より良いclassの分け方、.cssファイルの分け方、classの命名の仕方、など多岐に渡ります。
必ず正解といえるものがあるわけではなく、勉強した上でもやはり悩むものは悩むんですが、現場で使われている習慣的なものを知っていればコードを読み書きするときにきっと役立つと思います。

## ようやく本題。CSS設計手法をいくつか見てみる
さて、本題に入りましょう。CSS設計。[前回の記事](https://qiita.com/nanarya/items/661ec10ff262c84424a6)を見るとOOCSS、SMACSS、BEMと並んでますね。この3つが代表的なCSS設計手法のようです。それぞれ簡単に解説してみましょう。

- OOCSS(オブジェクト指向CSS)  
オブジェクト指向という単語を聞いたことはあるでしょうか。要は一度書いたものはうまいこと使い回ししていこうというプログラミングの考え方なんですが、それをCSSに持ち込んだのがこのOOCSSです。さっきの例で言えばbuttonというclassを別のところで使えるように設計する、というような感じです。
- SMACSS  
CSSを5つのカテゴリに分割して制作してメンテナンス性を高めようという考え方です。要素のデフォルトを決めるベースや個々の再利用可能なパーツのモジュールなどに分けてCSSを組み立てていきます。CSSのクラスの分け方やデータの分割方法など、カテゴライズしながら作るというのが考え方の中心にあります。
- BEM  
Block Element Modifierの略です。大きいくくりのBlock、その中にあるパーツであるElement、特殊な状態や修飾の際に使うModifierの3つに分けてCSSを命名していく、命名規則です。命名規則のみのため、CSSデータの分割方法などは含まれませんが、他に比べ命名のルールが厳密です。

今回はこの中からBEMを取り上げたいと思います。
理由は「よく使われている」「覚えやすい」この2点です。「なんとなく書ける」から一歩先へ進むための勉強にはちょうど良いと思います。
OOCSSは概念的で掴みづらい。SMACSSは覚えることが多く、大規模なページでないと効果が実感しづらい。という印象があるので、今回はまずBEMでいきましょう。
組み合わせて使ったりもできるので、興味がある人は他の2つも調べて見てください。

## BEMを勉強する！
### BEMを3行で説明してみる
先ほども書きましたがBEMはBlock Element Modifierの略です。
`block__element--modifier`と書きます。
例えば「メニュー内にある赤いボタン」は`menu__button--red`となります。

基本的にはこれだけです。ね、簡単でしょ？

### もうちょっとちゃんと説明します
流石に前置きの1/10しか本文がなかったら怒られそうなのでもうちょっと書いてみます。
BEMは__classの命名手法__で「ベム」と読みます。
一番有名な命名手法で、仕事の現場でもよく見かけるため、これがわかると初めて見るコードでも掴みやすくなると思います。
ちなみに、命名手法については正しくはMindBEMdingというもので本来のBEMとはルールが多少違うようですが、このMindBEMdingが一般的にそのままBEMと呼ばれていることも多いようなので、BEMといったら`block__element--modifier`で大丈夫だと思います。
なお、BEM（否MindBEMding）は`block__element_modifier`と書くようです。

ElementはBlockの子要素なので必ずBlockのあとにつきますが、
ModifierはBlockの修飾をする場合とElementの修飾をする場合で2パターンあります。（下に詳しく書きます）
ただ、亜種が色々あったり、実際の現場ではアレンジされていることもあるので、Block Element Modifierの3つに分かれているという大原則が掴めれば良いと思います。

### 実際の書き方とか
`block__element--modifier`が基本の形ですが、細かい書き方やアレンジも見ていきましょう。

- Blockのみの大枠のクラスの場合`block`
- Blockの修飾をする場合`block--modifier`
- Blockの子要素の場合`block__element`
- Elementを修飾する場合`block__element--modifier`
- Block等に2つ以上の単語が入る場合  
`block-name__element-name--modifier-name(key_value)`というように単語を「-」で区切る書き方になります。
- modifierについてはkeyにあたるものを省略したりしなかったりします。  
例：`button--color_red`や`button--red`などの書き方があります。
- そのほか独自のアレンジがされているかもしれません  
例：[BEMを参考にしたCSS設計](https://qiita.com/mrd-takahashi/items/07dc3b4bad027daa2884)

実際に書いてみるとこんな感じです。

```html:index.html
<article class="post">
  <h1 class="post__title">タイトル</h1>
  <p class="post__text">本文本文本文本文</p>
  <a class="post__button　post__button--good">いいねボタン</a>
</article>
```
パッと見て、「-」や「\_」で単語が区切れていたら「おっ、これはBEMかな？」という見方ができると思います。
この基本形がわかると、多少見た目が違ってもコードを見たときに概要が掴みやすくなります。

### さらに詳しく見てみる
※コメントいただきましたので追加しました。
上の例では

```html
<article class="post">
　　〜
</article>
```
となっているのでこの中が全て`post`Blockの中ですね。

```html
<h1 class="post__title">タイトル</h1>
<p class="post__text">本文本文本文本文</p>
```
その下にあるh1とpは`post`Blockの中にある`__title`Elementと`__text`Elementですね。
その次はちょっと難しくなります。

```html
<a class="post__button　post__button--good">いいねボタン</a>
```
となっているので、`post__button`と`post__button--good`の2つのクラスがついていることになります。
`post`Blockの中の`__button`Elementということで`post__button`。
`--good`の部分がmodifierになるので、`post__button`の`--good`Modifierで`post__button--good`。
ところでこのタグだけclassが2つついていますが、どのように捉えればよいでしょう。
`post__button--good`はModifier(修飾)になるので、基本となるclass`post__button`がついています。
つまり、Modifierがある場合は基本となるクラスがセットでつくことになるということです。
※ただし違う設計手法もあるようなので注意してください。
=\>[一番詳しいCSS設計規則BEMのマニュアル](https://qiita.com/Takuan_Oishii/items/0f0d2c5dc33a9b2d9cb1)

### 最初の問題をBEMで解決してみよう

```css:style.css
.button {
  width: 200px;
  background-color: red;
}
```
これをそのまま流用してしまうとボタンが赤くなってしまうので青いボタンが作れないという話でしたね。
BEMの考え方で作るなら、こんな感じでしょうか。

```css:style.css
.button {
  width: 200px;
  background-color: red;
}
.button--blue {
  background-color: blue;
}
```
これだけです。
青いボタンを作りたいときは、このCSSに

```html:index.html
<div class="button button--blue">
```
というHTMLが組み合わされればボタンは青くなります。
赤と青が両方書かれているのに良いの？と思った方は詳細度なんかを調べてみてください。
=>[エンジニアはもう一度CSSとちゃんと向き合ってみよう - 詳細度編](https://qiita.com/izumin5210/items/8ae78cb4f4bd325bccb4#a3)
BEMではBlockごとにCSSを書いていくことになるので、この方法でも問題は起きにくいのではないかと思います。（他に良い解決法があればコメントください！）

## BEMだけじゃ足りないもの
さて、簡単にBEMの要素を見てもらいました。
classの命名については法則に従うことでちょっとだけプロっぽく書けるようになったんじゃないでしょうか。
でも、それだけですね。まだまだ足りないものがあります。
最後にそのあたりを簡単に見ていきましょう。

### class名で使う単語はどうすればいいの？
いきなり命名についてです。そう、BEMをなんとなく覚えてもclassの命名はやっぱり悩みます。
ボタンが2種類あったとして
`button--red`/`button--blue`とするのか
`button--primary`/`button--secondary`とするのか
`button--a`/`button--b`とするのか
`btn--big`/`btn--small`みたいな書き方もあると思います。
これについては明確な答えはありません。
ただ、一般的には内容がわかりやすい命名が良いとされている傾向があるように思います。
しかし、`--a`/`--b`という命名も、後から色や形が変わっても名称と内容の関係が破綻しないという強みがあります。
そのときどきに応じて最良の選択する必要がありそうです。

| パターン      | 見た目から名付ける | 役割、機能から名付ける | 記号的に名付ける |
|:-----------:|:--------------:|:-----------------:|:-------------:|
| class名     | button--red    | button--primary   | button--a     |
| 内容の予測が  | 非常にしやすい    | ある程度しやすい      | しづらい        |
| 変更・拡張に   | 非常に弱い       | ある程度強い         | 非常に強い     |

`button`と`btn`については、誰にでも分かるように`button`と書くようにと書いてある本もあれば、`btn`のようにルールで定めて識別子のような形に省略しましょうと書いてる本もありましたね。こちらも一長一短なのでチーム内で統一することだけ意識しておけばいいんじゃないでしょうか。

class命名時に役立ちそうな良い記事があったのでメモがわりに残しておきます。
=\>[CSSのクラス名を決めるときに使うリストをつくりました](https://qiita.com/manabuyasuda/items/dbb76ed36970bec95470)

### .cssのデータは1つでいいの？
こちらは規模にもよりますが、分けた方がメンテナンス面でアドバンテージがありそうです。
ただし、.cssのまま分割していくのはあまりよくないでしょう。分割する場合はメタ言語（SCSS他。プリプロセッサとも呼びます）などを使うのがスマートですね。つまり、（SCSSの場合）.scssをカテゴリやパーツごとに分割して作って、最終的に1つの.cssにまとめる、という手法になります。メタ言語についても書き始めると長くなってしまうので割愛します。
ちなみに、BEMには.cssの分割方法は特に規定されていません。それでも、闇雲に分けるのはナンセンスです。BEMのブロック構造の通りに分割するのも手ですが、ディレクトリ構造について勉強してみたい方はSMACSSを学んでみると良いと思います。

### classは1つしかつけないもの？複数つけて良いもの？
これはCSS設計によって変わってきます。
BEMは基本的には先ほども書きましたが、modifierがあるときのみ複数クラスで書いていくことが多いようですが、OOCSSなんかは複数クラスをつける前提の設計手法ですね。
このあたりは自分の得意不得意や制作物との相性を考えて、どの設計手法を使うかを考える必要がありそうです。
もちろんチーム内で共有できるようであればルールをアレンジしてつかっても良いと思います。

### CSS設計手法はとりあえずBEMを使えばいいの？
とりあえずBEMをつかっておけばちょっとだけそれっぽくなるかもしれません。
ですが、CSS設計手法にも向いている向いていない制作物があります。
例えばBEMはBlock--Elementという書き方をするためclass名が長くなりがちですが、他のコンテンツとのclass名の競合などがおきづらいです。複数人での案件や、人の出入りがある案件では使いやすいでしょう。
BEMには.cssの分割方法は含まれていないので、そのあたりも知りたいという方はFLOCSSという設計手法を調べてみてください。
[FLOCSS](https://github.com/hiloki/flocss)

## おわりに
CSS設計およびBEMを非常に簡単に解説しましたが、ちゃんと勉強するともっとずっと奥が深いです。今回は氷山の一角、導入部分程度。なので、もし興味が出てきた人は自分で調べてみてください。Qiitaにもとても良い記事が多くあるので、勉強になると思います。
偉そうに書いてますが、筆者自身まだまだフロントエンド初学者。軽く触った程度なので改めて勉強する機会を作ろうかと思います。
また、記事の内容については調べた上で記載していますが、間違いがあるかもしれません。もし見つけた先輩方がいらっしゃったら、私とこれから学ぶ方のためにぜひコメントにて教えていただければと思います。
それと、これを読んでもわからないところとかがあれば教えてください。自分の勉強も兼ねて追記したいと思います。
末筆ですがここまでご覧いただきありがとうございました。

さて、次は何を勉強しよう。

##参考書籍等
[はじめてのCSS設計 / 翔泳社](http://www.shoeisha.co.jp/book/detail/9784798143156)
[最強のCSS設計 / SBクリエイティブ](http://www.sbcr.jp/products/4797384550.html)
[BEMを参考にしたCSS設計 / Qiita](https://qiita.com/mrd-takahashi/items/07dc3b4bad027daa2884)
[CSSのクラス名を決めるときに使うリストをつくりました / Qiita](https://qiita.com/manabuyasuda/items/dbb76ed36970bec95470)
ほか