CSSの命名規則BEMについて

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ CSSの命名規則BEMの概要・命名規則・HTMLとSCSSでの書き方

## 概要

HTMLにクラス名をつける時の代表的な命名規則には以下の3つがあります。
この記事ではBEMについて深堀りをしたいと思います。

・ BEM（Block-Element-Modifier）：ベム

・ OOCSS（Object Oriented CSS）：オーオーシーエスエス

・ SMACSS（Scalable and Modular Architecture for CSS）：スマックス

## CSSの命名規則について

命名規則が統一されていれば、HTMLを書いている時にクラス名を何にするか悩まなくなり、素早くHTMLのマークアップを行えるようになります。

#### BEM

BEM（ベム）は、Block、Element、Modifierの頭文字をとったもので、厳格なクラスの命名規則が
特徴のCSS設計です。ページを構成する要素をこの3つのどれかに当てクラス名をつけます。

#### BEMを使うメリット

##### クラスの命名が簡単になる

CSSの設計においては、命名規則が最も難しいとされています。
BEMでは、Block、Element、Modifierの3つに分類して考え、これらのみでクラスを命名することで
クラス名で悩むことがなくなります。

##### 要素の再利用がしやすくなる

共通の要素を別の場所で再利用しようとしても、要素がHTMLに依存していると
同じCSSを書かなければなりません。しかし、BEMを使うことでクラスの命名がHTML構造に依存せずに
要素を再利用しやすくなります。

#### BEMのデメリット

クラス名が冗長で、全ての要素にクラス名を付与するのでHTMLが読みにくくなります。
また、BootstrapはOOCSSを採用しており、BEMとの相性がいいとは言えません。

## BEMを構成する要素

個性的（？）なキャッチフレーズが印象の株式会社hogeの~~適当に作った~~HP構成です。
これを元にBEMを構成する3つの要素を説明します。

<font color="gray">※赤枠がBlock、緑枠がElement、紫枠がModifierを示しています。</font>

![スクリーンショット 2021-01-25 15.04.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/fd23ea64-9d58-6daa-475d-7c84388f16bb.png)

#### Block

要素の大元となるブロック要素です。パーツとして独立完結していて場所を問わず機能します。
Block内にBlockが入れ子になっていてもOKです。

#### Element

Elementは必ずBlockの中に存在します。
同じElementが複数存在しても良いですし、Element内にElementが入れ子になっていてもOKです。

#### Modifier

パーツ構成は同じですが、見た目や動きが違うパーツを作成する際にModifierを使用します。
BlockもしくはElementに付与し、1つのパーツに複数Modifierを付与してもOKです。

## BEMの命名規則

Block、Element、Modifierの命名規則について説明します。

#### Block

![スクリーンショット 2021-01-25 16.52.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/4e5f0682-0911-1b6b-dae1-fb463169dffd.png)

例えば上記のようなロゴは、ヘッダーのロゴなのでHeaderLogoと命名します。
**クラス名の単語が2つ以上の場合は、単語の間にキャメルケースまたはスネークケースでつなぐか
『-』ハイフンを入れます。**

```html
<div class="HeaderLogo"></div>
```

もしく下記のように書きます。

```html
<div class="Header-logo"></div>
```

**BEMで全てのデザインを管理できればよいのですが、BEMから外れてデザインをすることに備え
BEMとそれ以外を区別するためBlock名をパスカル記法（最初を大文字）にすると分かりやすくなります。**

#### Element

![スクリーンショット 2021-01-25 17.11.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/8a0359b1-d62d-d1d3-c236-2f6673870fda.png)

**ElementはBlock名の後に『_』アンダースコア2つでつなぎます。**

このアンダースコア2つを**セパレーター**や**区切り文字**といい、後述のModifierの区切りや
名前の区切りと判別できるようにします。

```html
<div class="HeaderLogo">
  <div class="HeaderLogo__picture">
    <img class="Logo__img" src="logo.jpg" alt="ロゴ">
  </div>
  <div class="HeaderLogo__text">
    <div class="Logo__title">株式会社hoge</div>
    <div class="Logo__subtitle">フューチャーを、未来する</div>
  </div>
</div>
```

#### Modifier

![スクリーンショット 2021-01-25 17.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/3c6a58f5-f58d-4670-783f-3687fdbdac8b.png)


**ModifierはBlock名やElement名の後に『-』ハイフンを2つでつなぎます。**

```html
<div class="About">
  <div class="About__title">ABOUT</div>
    <p class="TopTitle">・hogefuga</p>
  <div class="About__title">ABOUT</div>
    <p class="TopTitle--square">■hogefuga</p>
</div>
```

## SCSSの記述

簡単にですが、下のようなhtmlにscssで記述しました。

![スクリーンショット 2021-01-26 11.22.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/379bdde4-4deb-0b03-cc4a-207a7a6204ff.png)


```html:index.html
<div class="HeaderLogo">
  <div class="HeaderLogo__picture">
    <img class="Logo__img" src="logo.jpg" alt="ロゴ">
  </div>
  <div class="HeaderLogo__text">
    <div class="Logo__title">株式会社hoge</div>
    <div class="Logo__subtitle">フューチャーを、未来する</div>
  </div>
</div>
```

```scss:style.scss
.HeaderLogo {
  display: flex;
  justify-content: center;
  align-items: center;
  background: #eee;
  border-radius: 5px;
  height: 100px;
  width: 350px;
  padding: 10px;
  &__picture {
    display: block;
    margin-right: 30px;
  }
  &__text {
    .Logo__title {
      color: green;
    }
    .Logo__subtitle {
      color: red;
    }
  }
}
```

#### SCSSで記述する際のルール

##### element、modifierは親セレクタから参照し、ネストを使って定義する

<font color="gray">* modifierである.HeaderLogo__picture--sampleは適当に今作りました</font>

```scss:style.scss
.HeaderLogo {
  // 省略
  &__picture {
    display: block;
    &--sample {
      color: red;
    }
  }
}
```

##### element内で更にelementをネストさせて定義してはいけない

下の例ではElement(.HeaderLogo__picture)の中にElement(.HeaderLogo__picture__subpicture)がネストしており、
これはHTMLとSCSSを分離させるという意味でよくありません。

```scss:style.scss
.HeaderLogo {
  // 省略
  &__picture {
    display: block;
    &__subpicture {
      padding: 10px;
    }
    &--sample {
      color: red;
    }
  }
}
```

HTMLとSCSSの構造を分けると、デザイン仕様が変わっても少ない修正で済みます。
elementがBlock以外に親を持ってしまうとHTMLとSCSSを分離できなくなってしまい、コードの修正や拡張しにくいコードとなってしまいます。

## 関連記事

[BEMで命名する名前を予め考えておく](https://qiita.com/s79ns/items/47e6bcfec727791d91e7)