Learning site for website creation

CSSの命名規則BEMのルールとカスタマイズ

  • 投稿日:2020年10月19日
  • 更新日:2020年10月20日

よく使われるclass名の命名規則

HTMLにclass名をつける時の代表的な命名規則には以下の3つがあります。今回はこの中のBEMについて紹介します。

  • BEM(Block-Element-Modifier:ベム)
  • OOCSS(Object Oriented CSS:オーオーシーエスエス)
  • SMACSS(Scalable and Modular Architecture for CSS:スマックス)

BEMとは

BEM(ベム)はHTML要素を「Block」「Element」「Modifier」に分けてclass名をつけます。この3つの頭文字を使って「BEM」と呼びます。

BEMのメリット

  • パーツ単位でデザインを管理する為、変更時に他のパーツへの影響を考慮しなくていい
  • セレクタを入れ子にしないので優先度問題が発生しにくい
  • BEMを採用している会社が多い

BEMのデメリット

  • class名が長い
  • すべての要素にclass名を付与するのでHTMLが読みづらくなる
  • Bootstrapとの相性が悪い(BootstrapはOOCSSを採用している)

HTML要素をパーツ単位で管理:Block

BEMではHTML要素をパーツ単位で管理します。このパーツを「Block」として扱います。以下のワイヤーフレームをパーツ単位でBlock作成してみます。

Blockのルール

  • パーツとして独立完結しており別場所に移動しても機能する
  • Block内にBlockが入れ子になってもOK
    ※ただしスタイルはBlock単位で記述し、複数のBlockをまたいでの子孫セレクタを使用しない

「ヘッダーパーツ」「アイキャッチパーツ」「紹介パーツ」で構成されています。

「ヘッダーパーツ」内には「ロゴパーツ」「ヘッダーナビパーツ」「お問い合わせパーツ」。「紹介パーツ」内には「紹介項目パーツ」が入れ子になっています。

赤枠で囲ったこれらのパーツが「Block」と考えることができます。

パーツ内の部品:Element

パーツ(Block)内の部品を「Element」として扱います。緑枠がElementになります。

Elemantのルール

  • 必ずBlock内にある
  • 同じElemantが複数存在してもOK
  • Element内にElementが入れ子になってもOK
    ※入れ子が深くなる時はElement内でBlockを作成できないか検討する

パーツのバリエーション(状態):Modifier

パーツ構成は一緒だが「見た目」や「動き」の違うパーツを作成する際にModifierを使用します。

以下の例の場合、紫枠パーツが他のパーツと構成は一緒だが「マーカー(行頭記号)」が「○」と「■」で違っています。この場合は既存のBlockやElementに「Modifier」を付与してデザインを定義します。

Modifierのルール

  • 既存のBlockもしくはElementに付与する
  • 1つのパーツに複数Modifierを付与してもOK

BEMの命名規則

Block

class名は必ずBlock名から開始します。

  <div class="Block名">

  </div>

例えば上記のロゴの場合はこのように命名します。

  <div class="logo">

  </div>

Element

ElementはBlock名の後に「_(アンダースコア)」を2つでつなぎます。この「_(アンダースコア)」2つを「セパレーター」や「区切り文字」と呼び、後述のModifierの区切りや名前の区切りと判別できるようにします。

  <div class="Block名__Element名">

  </div>

例えば上記のロゴの場合はこのように命名します。基本的にBlock内のElementすべてにclass名を指定します。最初はElement名をどうすればよいのか迷うのでdiv要素の場合は文章構造的な名前を、その他要素はHTML要素名を使用するとよいかもしれません。

  <div class="logo">
    <div class="logo__main">
      <img class="logo__img" src="img/logo.png" alt="ロゴ">
    </div>
    <div class="logo__sub">
      <div class="logo__company-name">株式会社XD</div>
      <div class="logo__company-text">会社の説明が入ります</div>
    </div>
  </div>

名前が2つ以上の単語になる場合

BlockやElementの名前の単語が2つ以上になる場合は「-(ハイフン)」で単語をつなぎます。

      <div class="logo__company-name">株式会社XD</div>
      <div class="logo__company-text">会社の説明が入ります</div>

Modifier

ModifierはBlock名やElement名の後に「-(ハイフン)」を2つでつなぎます。

  <div class="Block名__Element名--Modifier名">

  </div>

例えば上記のパーツの通常パーツを作成します。

  <div class="intro-item">
    <div class="intro-item__photo">
      <img class="intro-item__img" src="img/photo.png">
    </div>
    <div class="intro-item__title">
      タイトルが入ります
    </div>
    <div class="intro-item__text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="intro-item__list">
      <li class="intro-item__list-item">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

リストのマーカーが「○」「■」で違うパーツにModifierを付与します。ul要素のclass名「intro-item__list」にModifier「intro-item__list--square」を追加します。

  <div class="intro-item">
    <div class="intro-item__photo">
      <img class="intro-item__img" src="img/photo.png">
    </div>
    <div class="intro-item__title">
      タイトルが入ります
    </div>
    <div class="intro-item__text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="intro-item__list  intro-item__list--square">
      <li class="intro-item__list-item">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

名前が2つ以上の単語になる場合

先程はElementで使用しましたが、Blockでも名前の単語が2つ以上になる場合は「-(ハイフン)」で単語をつなぎます。

  <div class="intro-item">

  </div>

命名規則をカスタマイズ(変則BEMを考える)

BEMはclass名が長くなるというデメリットをもっています。そのデメリットを少しでも軽減するための工夫。

名前が2つ以上の単語になる場合

名前の単語が2つ以上になる場合は「-(ハイフン)」で単語をつないでいましたがキャメルケース記法で命名する。

  <div class="intro-item">

  </div>

キャメルケース記法(2つ目以降の単語の頭文字を大文字にしてつなぐ)に変換します。

  <div class="introItem">

  </div>

BlockとElementとModifierの区切りを短くする

名前の単語が2つ以上になる時をキャメルケース記法にすることでModifier「-(ハイフン)」を2つにする必要がなくなり「-(ハイフン)」を1つでつなぐことができます。

Modifierに合わせてElementも「_(アンダースコア)」を1つでつなぎます。

  <div class="intro-item">
    <div class="intro-item__photo">
      <img class="intro-item__img" src="img/photo.png">
    </div>
    <div class="intro-item__title">
      タイトルが入ります
    </div>
    <div class="intro-item__text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="intro-item__list--square">
      <li class="intro-item__list-item">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

上記をカスタマイズ版に変更します。ElementやModifierのつなぎが2つから1つに変更されます。

  <div class="introItem">
    <div class="introItem_photo">
      <img class="introItem_img" src="img/photo.png">
    </div>
    <div class="introItem_title">
      タイトルが入ります
    </div>
    <div class="introItem_text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="introItem_list-square">
      <li class="introItem_listItem">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

Modifierをclass名から分離する

Modifierはバリエーションの為、「基本デザインのクラス名」に「Modifireのクラス名」を追加する形で記述します。

こうすることで複数Modifierを付与しても簡潔になります。

元の複数Modifier

    <ul class="introItem_list introItem_list-square introItem_list-pickup">

    </ul>

カスタマイズした複数Modifier

    <ul class="introItem_list  -square  -pickup">

    </ul>
  <div class="introItem">
    <div class="introItem_photo">
      <img class="introItem_img" src="img/photo.png">
    </div>
    <div class="introItem_title">
      タイトルが入ります
    </div>
    <div class="introItem_text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="introItem_list  introItem_list-square">
      <li class="introItem_listItem">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

上記をカスタマイズ版に変更します。Block名やElement名の後に「半角スペース」を入れ「Modifierを別クラス」として記述します。ただしModifierを意味するセパレータの「-(ハイフン)」を接頭辞として付与します。

  <div class="introItem">
    <div class="introItem_photo">
      <img class="introItem_img" src="img/photo.png">
    </div>
    <div class="introItem_title">
      タイトルが入ります
    </div>
    <div class="introItem_text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="introItem_list  -square">
      <li class="introItem_listItem">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

クラス名を分離した為、CSSは以下のような記述になります。

.introItem_list {
  基本デザインを定義
}

.introItem_list.-square {
  基本デザインから変更するところだけを定義
}

BEM以外のclass名を共存させるためBEM記法を明示する

BEMですべてのデザインを管理できればよいのですが、どうしてもBEMから外れてデザインすることもでてきます。BEMとそれ以外を区別するためにBEMのBlock名はパスカル記法(すべての単語の頭文字を大文字にする)を使用します。

  <div class="introItem">
    <div class="introItem_photo">
      <img class="introItem_img" src="img/photo.png">
    </div>
    <div class="introItem_title">
      タイトルが入ります
    </div>
    <div class="introItem_text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="introItem_list  -square">
      <li class="introItem_listItem">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

上記をカスタマイズ版に変更します。Block名「introItem」が「IntroItem」になります。

  <div class="IntroItem">
    <div class="IntroItem_photo">
      <img class="IntroItem_img" src="img/photo.png">
    </div>
    <div class="IntroItem_title">
      タイトルが入ります
    </div>
    <div class="IntroItem_text">
      親譲りの無鉄砲で小供の時から損ばかりしている。
      小学校に居る時分学校の二階から飛び降りて
      一週間ほど腰を抜かした
    </div>
    <ul class="IntroItem_list  -square">
      <li class="IntroItem_listItem">
        親譲りの無鉄砲で小供の時から損ばかりしている。
      </li>
                 :
    </ul>
  </div>

案件内でルールが統一されていればよい為、より使いやすいようにBEMをカスタマイズしてみることをお勧めします。