🏃‍♀️

5分で理解するBEM

2021/03/15に公開

この記事は

フロントエンド初心者が、「BEMって何?」と思ったときにさっと概観を理解でき、BEMに従って簡単なマークアップをできるようになることを目指したもの。

BEMとは?

CSSの設計手法の1つ。
他に有名なCSS設計手法として、OOCSS、SMACSS、FLOCCSなどがある。

B(Block)、E(Element)、M(Modifier)の略である。

サンプルコード

<!-- block -->
<div class="header">
    <!-- block -->
    <div class="logo"></div>

    <!-- block -->
    <form class="search-form search-form_focused">
        <div lass="search-form__content">
            <!-- element -->
            <div class="search-form__label">
                <!-- block -->
                <div class="search-label-text">検索</div>

                <!-- block -->
                <div class="search-label-icon"></div>
            </div>

            <!-- element -->
            <input class="search-form__input">

            <!-- element -->
            <button class="search-form__button search-form__button_size_m"></button>
        </div>
    </form>
</div>

Block、Element、Modifierそれぞれの説明

Blockとは

公式ドキュメントのBlockの定義

A functionally independent page component that can be reused. In HTML, blocks are represented by the class attribute.

機能的に独立しており、あらゆる場所で再利用ができるパーツのこと。
これを実現するため、例えばBlockにはそれ自体の位置を決めるようなCSSを書くべきではない。

Elementとは

公式ドキュメントのElementの定義

A composite part of a block that can't be used separately from it.

Blockを構成するパーツのこと。

クラス名には必ずBlock名を入れ、Block名__Element名のような形式にすること。

Elementは必須ではないので、Blockの下にElementを置かないのもOK(例:サンプルコードのlogo)

Modifierとは

公式ドキュメントのElementの定義

An entity that defines the appearance, state, or behavior of a block or element.

BlockやElementの見た目や状態や振る舞いを定義するもの。
1つのBlockやElementに対し、複数のModifierをつけることができる。

命名の仕方には2パターンある。

クラス名(Boolean)

クラス名は、

  • Block名_Modifier名(Blockの場合)
  • Block名__Element名_Modifier名(Elementの場合)
    のような形式にすること。(例:サンプルコードのsearch-form_focused

クラス名(Key-value)

「ある項目が」(Key)「ある値で」(Value)あるModifierという名前づけができる。(例:サンプルコードのsearch-form__button_size_mは、sizeがKey、mがValue。中サイズのボタンのスタイル指定となっている。)
クラス名は、KeyとValueをアンダースコア区切りにする。

  • Block名_Modifier(Key)_Modifier(Value)(Blockの場合)
  • Block名__Element名_Modifier(Key)_Modifier(Value)(Elementの場合)
    のような形式にすること。

Block、Elementのスタイルを組み合わせる「Mix」

公式ドキュメントのMixの定義

A technique for using different BEM entities on a single DOM node.

単一のDOMノードに、複数のBEMエンティティを適用すること。

今まで見てきた例では、1つのHTMLタグはBlockかElementどちらかの1つの役割になっていたが、例えば以下のようにBlock(search-form)でもありElement(header__search-form)でもあるという状態にすることができる。

<!-- `header` block -->
<div class="header">
    <!--
        The `search-form` block is mixed with the `search-form` element
        from the `header` block
    -->
    <div class="search-form header__search-form"></div>
</div>

これにより、「Blockとして指定したいスタイル」「Elementとして指定したいスタイル」がそれぞれある場合に分離して書いた上で組み合わせて適用ができるので再利用性が高まる。
他の場所でも再利用できるようなformというパーツそのもののスタイル定義はBlock(search-form)に、位置合わせなど配置される場所に依存するスタイル定義はElement(header__search-form)として記述するとよい。

.search-form {
    border:  1px solid black;
    padding: 10px;
}

.header__search-form {
    margin-top: 30px;
}

なお、今回はBlockが1つ・Elementが1つとなっているが、複数指定することも可能。

File Structure

BEMはHTMLやCSSの構成だけでなく、ファイルの分割方法についても規則がある。

  • 1 Blockあたり1ディレクトリ。配下にElementとModifierを定義したディレクトリを配置
  • Block名とディレクトリ名は同じにする
  • Elementのディレクトリ名は__から始まる
  • Modifierのディレクトリ名は_から始まる

補足

ネストについて

  • Blockの中に別のBlockを置くことはOK

    • サンプルコードでのheaderlogoのような感じ
  • Elementの中に別のElementを置くこともOKだが、名前に気をつけること

    • サンプルコードのsearch-form__contentsearch-form__inputのような感じ
    • 必ず、名前によりどこのBlockに含まれるものかを明確化する
  • Elementの中に別のBlockを置くこともOKだが、こちらも名前に気をつけること

    • サンプルコードのsearch-form__labelsearch-label-textsearch-label-iconのような感じ
    • 中のBlockは親のElement名は引き継がない
  • 上位BlockのないElementはNG

    • CSSのスコープを限定するために重要な規則

BlockとElementの使い分けは?

何らかのパーツの下でのみ使われるパーツは、Elementにすべき。サンプルコードのsearch-formの下のElementがわかりやすい。
逆に、他の箇所でも使えるパーツはBlockにするとよい。

なんとなくBlockの中にElementというイメージで、Blockが大きなパーツでなくてはいけない気もしてくるが、独立していて・いろいろな箇所で再利用かどうかがBlockにするかどうかのポイント。

更に詳しく

Discussion