🍅

BEMのB.E.Mとはをざっくり理解したい人向け

2025/02/05に公開

BEMを理解したい、けどリファレンスをしっかり読むのはしんどいぜーって人に向けた、ライトなBEMの記事を書いてみようと思う

B・E・M それぞれの意味と役割

BEMとは「Block」「Element」「Modifier」3つの頭文字とってBEM(ベム)と呼び、スタイリングをその B>E>M の3段階のclassに分けてスタイルを作る手法である

ただ私は I am japanese なので、BEMそれぞれの意味をあえて日本語に置き換えて理解している
それが

  • Block = 領域
  • Element = 役割
  • Modifier = 装飾

だ、各個を詳しく見ていこう

Block (領域)

Blockとは簡単に言ってしまうとWEBページを構成する「セクション」や「パーツ」のこと
特に「セクション」が想像しずらいかもだが、例えばヘッダーやフッターや記事と言ったWebページの段落だと思ってもらうと良いかもしれない。
「パーツ」とはボタンやカードの様に「セクション」よりも少し小さい単位のものとなる

自作で恐縮だが、下記にZennのトップページをもし「セクション」「パーツ」で分けるならこうなるぞ
と言う参考画像を用意したので、理解の助けとなれば幸いだ
(厳密に分けたわけでは無いので、有識者からすると違和感があるかもしれないが、取っ掛かりやすさを重視してなるべくシンプルにまとめた)

そして2枚目の画像の枠で囲っている部分をコードにするとこうなる

<!-- ヘッダーブロック -->
<header class="header"></header>

<!-- インフォメーションブロック -->
<section class="info">
    <!-- インフォメーションカードブロック -->
    <div class="infoCard"></div>
</section>

<!-- 記事ブロック -->
<section class="article">
    <!-- 記事カードブロック -->
    <div class="articleCard"></div>
</section>

正直、どの範囲をBlockと捉えるか?はBEMの最初の一歩だがとても難しい
これに関しては経験を積んでいきその感度を高めていくほかないが、とりあえずBlockとは「セクション」や「パーツ」と言ったものを指すと理解して欲しい

※「セクション」「パーツ」と言う表現は、私がそう勝手にそう表現しているだけで、人によってはBlockを「パーツ」や「コンポーネント」と表現する時もある

Element (役割)

ElementとはBlock内にある、各要素の"役割"を指す
Elementがどんな物かを理解してもらうために、Zennの記事カードを例として用いていく
これをBlock>Elementまで作って行こう

先ずはブロック

<div class="articleCard"></div>

一旦、Blockまで作成した、class名はarticleCard(=記事カード)

ブロックの中身を役割毎に区切って行く

次に、記事カード(Block)の要素をElement(役割)毎にHTMLで分割していこう、最初はBEM作法に則るのではなく、日本語で考えていくと分かりやすいかもしれない、すると以下の様な役割に分割できるはずだ

  1. 記事カードのレイアウト
  2. 記事カードのサムネイル
  3. 記事カードのサムネイル画像
  4. 記事カードのコンテンツ
  5. 記事カードのタイトル
  6. 記事カードの詳細
  7. 記事カードのユーザーアイコン
  8. 記事カードのユーザーアイコン画像
  9. 記事カードのインフォメーション
  10. 記事カードのユーザーネーム
  11. 記事カードの投稿日
  12. 記事カードのお気に入り数

さてここまで出来たら、いよいよ上記12パーツをBEMの作法に則ってclass名に置き換えていこう
でも難しいことは無い、そのまま英語にしてしまえば良い、その際、単語を繋いでいる「の」はアンダーバー2つで表現する。以下の画像を参考にして欲しい

これを基に上記12パーツを実際のHTMLで表現すると以下の様になる

<div class="articleCard">
    <div class="articleCard__layout"><!-- 1 -->
        <div class="articleCard__thumbnail">"><!-- 2 -->
            <img class="articleCard__thumbnailImage" src="(画像パス)"><!-- 3 -->
        </div>
        <div class="articleCard__contents"><!-- 4 -->
            <div class="articleCard__title">タイトルが入ります。</div><!-- 5 -->
            <div class="articleCard__detail"><!-- 6 -->
                <div class="articleCard__userIcon"><!-- 7 -->
                    <img class="articleCard__userIconImage" src="(画像パス)"><!-- 8 -->
                </div>
                <div class="articleCard__userName">noteMan</div><!-- 10 -->
                <div class="articleCard__info"><!-- 9 -->
                    <div class="articleCard__postDate">1日前</div><!-- 11 -->
                    <div class="articleCard__favo">123</div><!-- 12 -->
                </div>
            </div>
        </div>
    </div>
</div>

これでElement要素の完成

一番外側にあるarticleCardというBlock要素のclass名を、Element要素は接頭辞として引き継いでいるのが特徴だ。

これにより、例えばarticleCardを移植・再構築する依頼があった際に、誰でも必要な要素をclass名から予想が出来るようになった

またElement要素を作る際には、いくつかの注意点があるので次の項で説明していく

Elementを作る際の注意点

1. Elementは必ずBlockの子要素であること(単独での使用不可)

これは言葉を尽くすよりも、下記の例を見てもらった方が直感的に理解できると思う
ダメなパターン

<div class="articleCard__title">タイトルが入ります。</div><!-- ここがダメ -->
<div class="articleCard">
    <!-- articleCardのElementはこの中に無ければならない -->
   ~~~
</div>

良いパターン

<div class="articleCard">
   <div class="articleCard__title">タイトルが入ります。</div>
   ~~~
</div>
2. Elementを2つ繋いではいけない

要は「記事カードのタイトルのサブタイトル」の様に、1つのclass名の中に2つのElement要素が入ってはならない。別の言い方で、孫要素はダメだよ!とも言われる
もっと簡単言うと、アンダーバーを2回使うな!てこと

ダメなパターン

<div class="articleCard__title">
    タイトルが入ります
    <div class="articleCard__title__subTitle">これはサブタイトルです</div><!-- ここがダメ -->
</div>

良いパターン

<div class="articleCard__title">
    タイトルが入ります
    <div class="articleCard__subTitle">これはサブタイトルです</div>
</div>

Modifier (装飾)

最後にModifier(装飾)について説明していく
Web製作をしていると、ほぼ同じパーツなんだけど少しだけ異なるものがあるだろう
Modifierとはこのほぼ同じパーツなんだけど少しだけ異なるものを作る時に活用するものだ

先ずは、下記画像を使ってModifierを感覚的に理解してみよう

上記トマトボックスの中で左から2番目のトマトボックスだけ「背景カラー」が異なっており、それ以外は全く同じパーツだ
これをElementの時と同様、上記パーツを日本語で表現すると以下の様になる

  • トマトボックス
  • トマトボックス(オレンジ)
  • トマトボックス
  • トマトボックス
    ※ 「トマトボックス」はBlock要素と考えて欲しい

ここまで出来たら後は簡単、これをBEMの作法に則って英語にするだけ
また()の部分をBEMでは「-(ハイフン)」2つで表現する

更にHTMLで表現すると以下の様になる

<div class="tomatoBox">~省略~</div>
<div class="tomatoBox tomatoBox--orange">~省略~</div>
<div class="tomatoBox">~省略~</div>
<div class="tomatoBox">~省略~</div>

ここからが大事なポイント!
上記のHTMLをよく見てみて欲しい、Modifierを付けた2番目のHTMLだけclassが2つ付いている
そう、Modifierを作る際は、BlockやElementのclassにマルチクラスとして追加するのだ

理由は単純、Modifierのclassは、BlockやElementに元々付与されているプロパティを継承し、差分だけのプロパティを記述するからだ、要は「少しだけ異なる」部分だけを追記する

.tomatoBox {
    widht: 412px;
    height: 500px;
    border-radius: 10px;
    padding: 20px;
    background-color: #ecf5ff;
}
.tomatoBox--orange {
    background-color: #ffe897; /* 少しだけ異なる部分だけ追記 */
}

またModifierはJavaScriptによって操作されるクラスにも利用されるので覚えておこう
最後にBEMのこれだけは知っておいて!というルールを1つ紹介して終わりにする

Block要素はMarginを持ってはいけない

Blockを扱う上でポイントとなるが Marginプロパティを付与してはいけない と言うこと
理由は単純、Block要素にMarginが付与されていると、それを再配置、再利用しようとした際に思わぬレイアウト崩れを起こしてしまうからだ(下記例)

「いやいや、そうは言ってもどうしても必要な時ってあるんじゃないの?」そう思った人もいるだろうがご安心あれ、BEM公式でちゃんと対処法について解答がある

Marginを付与したいBlock要素の、さらに上にあるBlock要素のelementをマルチクラスとして付与すればよい。

<section class="block-Z">
    <div class="block-A"></div>
    <div class="block-Z__layout">
        <div class="block-B"></div>
        <div class="block-B"></div>
        <div class="block-B"></div>
    </div>
    <div class="block-A block-Z__layout"></div>
</section>

Discussion