BEMのBlockはElementを入れ子にせずにコンポーネント化しよう

BEMでコーディングしていると、Elementが入れ子になってしまうことがありませんか?

設計になれないとどういう単位でBlockにしてコンポーネント化するのか迷ってしまうかと思います。

そこでBEMのBlockはどういう単位で作ればいいのか基準を紹介します。

BEMがよくわからない人は最初に「BEMでCSS設計する人のためのわかりやすいコーディングサンプル」を読んでみてください。

BEMでElementが入れ子になる

BEMで設計した時にどの単位でコンポーネント化するかは、クラス名に階層かできそうな場合に分けるのがよいと思います。

下記のコードはクラス名に階層がある場合です。

<div class="productList">
  <div class="productList__title">商品一覧</div>
  <div class="productList__list">
    <div class="productList__item">
      <div class="productList__box">
        <div class="productList__boxName">商品名</div>
        <div class="productList__boxPrice>価格</div>
      </div>
    </div>
  </div>
</div>

.productListというBlockの中に.productList__boxというElementがあります。

.productList__boxの中には更に.productList__boxNameというElementが存在し、クラス名の中で階層ができています。

たまに.productList__box__nameのように「__」単語で区切っているようなHTMLを見かけます。

どんどんBlockを大きくできてしまい、運用を始めると分かりづらくメンテナンス性も落ちる恐れがあるのでおすすめしません。

階層ができそうな場合は新しいコンポーネントとして定義していきます。

Blockを細かく切り出す

最初に紹介したコードはBlockが大きくなってしまいます。

そこで上記のように、クラス名に階層ができる場合には新しいBlockとして切り出しましょう。

例えば下記のようにBlockを細かくすることができます。

<div class="productList">
  <div class="productList__title">商品一覧</div>
  <div class="productList__list">
    <div class="productList__item">
      <div class="productItem">
        <div class="productItem__pame">商品名</div>
        <div class="productItem__price>価格</div>
      </div>
    </div>
  </div>
</div>

.productList__boxの部分を.productitemとして新しくBlock化します。

新しいBlockにしたことで.productItem__nameのように階層がなくなり、シンプルになりました。

Blockを入れ子にしていく

紹介した例では.productList__itemという.productListのElementの中に.productItemというBlockが入れ子になっています。

BEMはBlock → Elementという階層があるので、Elementの中にBlockが存在するのはいけないようですが、違うBlockになっているため問題ありません。

むしろElementの中にどんどんBlockが入れ子になっていく方が自然な設計です。

例えばページ全体をBEMで構成するとこんな感じになります。

<div class="header">
  <a href="#" class="header__brand">Brand Logo</a>
</div>
<div class="content">
  <div class="content__main">
    <div class="productList">
      <div class="productList__title">商品一覧</div>
      <div class="productList__list">
        <div class="productList__item">
          <div class="productItem">
            <div class="productItem__pame">商品名</div>
            <div class="productItem__price>価格</div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="content__side">
    <div class="widget">
      <div class="widget__title">検索</div>
      <div class="widget__body">
        <div class="searchForm">
          <input type="text" class="searchForm__input">
          <button class="searchForm__button">検索</button>
        </div>
      </div>
    </div>
  </div>
</div>
<div class="footer">
  <div class="footer__copy">copyright</dvi>
</div>

見てわかる通りBlockとElementが順番で入れ子になっているのがわかると思います。

BEMのBlockは細かくを心がける

BEMはElementにElementを入れ子にするとキリが無くなるほど、どんどん大きくなってしまいます。

また運用を続けるとクラス名は入れ子になっているのにHTMLの構造は入れ子になっていない、なんて状況にもなりかねません。

今回紹介したようなクラス名に階層ができてしまう場合は新しくBlockを定義することを、心がけるとBEMでのメンテナンス性はぐっとあがります。

この記事を書いた人

コウジ

TypeScriptとVue.jsが好きなフリーランスのフロントエンドエンジニアです。
フロントのHTML・CSS・JavaScriptの設計実装をメインに、RubyとNodeでサーバーサイドやってたりもします。

Web開発の仕事依頼

フリーランスのエンジニアとしてWeb開発の仕事をお引き受けしています。

依頼の検討をしていただきます際はポートフォリオサイトの事業・実績ページをご覧いただき、お問い合わせよりメールや各種SNSよりご連絡ください。

仕事の相談をする
基礎から学ぶ Vue.js