🚀

BEMについてのまとめ

2023/02/04に公開

今回は、BEMとはどんな設計手法なのか?
についてまとめました。

BEM = Block Element Modifierとは

BEMとは、CSSのクラス名を

  • どこの (Block)
  • なにに (__Element)
  • どのように (-Modifier)
    つけるかという分類で命名する規則です。

特徴

  • MindBEMdingがベース
  • csswizardryことHarry Robertsが提唱したCSSの命名規則
  • 1つの要素に対して、1つのクラスを指定する
  • 構造と見た目を分離して定義するOOCSS(Object Oriented CSS)やAtomic Designとの親和性が高い

BEMのルール

  • BlockとElementはアンダースコア2つ(__)で区切る
    例) block__element
  • BlockとModifier, ElementとModifierはハイフン2つ(--)で区切る
    例)block--modifier
    例)block__element--modifier
// Block = メニュー
<div class="menu">
   // Element = ボタン
  <div class="menu__item">
    // Modifier = 非活性状態
    <div class="button--disable"></div>
  </div>
</div>

Block

Blockはサイトを構成するパーツ、パーツの親要素です。
例)ボタン、グリッド、タブ、見出し、画像

BEMではBlockを起点とし、Blockを組み合わせることでサイトを構成します。

// DOM
<div class="box">
  <a href="/" class="button"></a>
</div>

// ブロック要素で余白を持ったシンプルなBlock
.box {
  display: block;
  padding: 1em;
}
// ボタンのスタイル
.button {
  display: inline-block;
  margin: 0;
  padding: 0.75em;
  border: none;
  border-radius: 3px;
  color: inherit;
  font-family: inherit;
  font-size: inherit;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  background: transparent;
  cursor: pointer;
  appearance: none;
  &:hover,
  &:active,
  &:focus {
    text-decoration: none;
  }
  &:disabled,
  &.is-disabled {
    opacity: 0.5;
    pointer-events: none;
  }
}

Element

Elementは、Blockを構成するパーツの1つ1つのことを指し、BEMではBlock(親要素)から見て下の階層にいる要素はすべてElement(子孫要素)として扱います。
例)ボタンやコンテンツ部分、見出しや画像

// .boxというBlockのElementとしてボタンを定義
// .box__button-itemは、色やサイズなどの装飾的な指定をする
<div class="box">
  <div class="box__button">
    <a href="#" class="box__button-item">button</a>
  </div>
</div>

Modifier

Modifierは、BlockとElementの状態を変えたいときに指定します。
Modifierは、例えばBlockのスタイルを変更することなく、背景色を変えるなどができるため、構造と見た目を分離でき便利です。

<div class="container container--gray"></div>

// Blockのスタイル
.container {
  display: block;
  padding: 1em;
}

// 背景色をgrayに変更する
.container--gray {
  background-color: gray;
}

BEMの良いところ

  1. 命名規則が明確
    • クラス名を見ただけでどんな要素かが分かりやすい
  2. 導入コストが低い
    • 明確なルールがあるので、一度導入すればコミュニケーションが円滑になる

注意点

BEMでは、BlockにいくつでもElementやModifierを足すことができる一方で、
多用しすぎると可読性が低くなる恐れがあります。

複雑化しやすいパターンとして、

  1. Element__Element
  2. Block__Element--Modifier

があります。

Element__Element

このパターンは、多階層のナビゲーションなどBlockから見て、孫要素ができる時に書いてしまいがちです。

<!-- NG -->
// element__elementでマークアップした場合
<ul class="nav">
  <li class="nav__item">
    <ul class="nav__item__items">
      <li class="nav__item__items__item"><a href="#" class="nav__item__items__link"></a></li>
      <li class="nav__items__items__item"><a href="#" class="nav__item__items__link"></a></li>
    </ul>
  </li>

  <li class="nav__item">
    <ul class="nav__item__items">
      <li class="nav__item__items__item"><a href="#" class="nav__item__items__link"></a></li>
      <li class="nav__items__items__item"><a href="#" class="nav__item__items__link"></a></li>
    </ul>
  </li>

</ul>

<!-- Good -->
// Block
<ul class="nav">
// Block__Element
  <li class="nav__items">
// Block__Element
    <ul class="nav__child-items">
      <li class="nav__child-item"><a href="#" class="nav__child-link"></a></li>
      <li class="nav__child-item"><a href="#" class="nav__child-link"></a></li>
    </ul>
  </li>

  <li class="nav__items">
    <ul class="nav__child-items">
      <li class="nav__child-item"><a href="#" class="nav__child-link"></a></li>
      <li class="nav__child-item"><a href="#" class="nav__child-link"></a></li>
    </ul>
  </li>

</ul>

Block__Element--Modifier

以下のように、ElementにModifierを指定すると、冗長になります。
基本的に、Block--Modiferを起点にしてスタイルを指定すると見やすくなります。

<!-- NG -->
<div class="box">
  <div class="box__element box__element--pad-large"></div>
  <div class="box__element box__element--pad-large"></div>
</div>

.box__element {
  padding: 1em;
}
// Elementのpaddingを変更するModifier
.box__element--pad-large {
  padding: 2em;
}

<!-- Good -->
<div class="box box--pad-large">
  <div class="box__element"></div>
  <div class="box__element"></div>
</div>

.box__element {
  padding: 1em;
}

.box--pad-large > .box__element {
  padding: 2em;
}

ディレクトリでCSSを管理する方法

SMACSS, Scalable and Modular Architecture for CSS

CSSを以下5つに分類し、各ディレクトリにファイルを保存します。
共通化ができるので、再利用性が高いのと、ディレクトリごとに分けてるので見やすく、管理しやすいのが特徴です。

  • Base:サイト全体に影響するもの(リセットCSSや変数の定義など)
  • Layout:ページのレイアウト(ヘッダー、フッターなど)
  • Module:再利用可能なパーツのこと(繰り返し使うボタンなど)
  • State:状態によって見た目が変化するもの(色の変化など)
  • Theme:テーマごとのスタイルのこと(サイトをダークモードにガラッと変えるなど) |

その他

  1. 「1ページに1度しか登場しないレイアウト」についてはIDセレクタが容認される
  2. LayoutカテゴリやStateカテゴリにあたるクラスには、接頭辞をつけることが推奨されている

FLOCSS, Foundation Layout Object CSS

FLOCSSは、SMACSSのようにモジュールを切り分けられるなど、他の有名なCSS設計を上手く取り入れて設計されています。

フォルダ構成例

  • Foundation:デフォルトスタイル
    • reset.css
    • variable.css etc.
  • Layout:各ページを構成するサイト全体で共通したエリア
    • l-hader
    • l-footer etc.
  • Object:サイト全体で再利用できるパターンを持つモジュール
    • Component:小さな単位のモジュール
      • c-button.css
      • c-grid.css etc.
    • Project:いくつかの↑Componentと、他の要素によって構成される大きな単位のモジュール
      • p-list.scss
      • p-card.scss
    • Utility:ComponentとProjectのモディファイア(パターン)で解決することができないスタイル、また、調整のための便利クラスなど
      • u-margin.css
      • u-padding.css

参考

BEM(MindBEMding)によるCSS設計
BEM(MindBEMding)についてややこしくない説明をしてみた
BEMとは何か
CSSの設計(OOCSS, BEM, SMACSS, FLOCSS)
FLOCSSのまとめ

Discussion