🤔

Split BEMというCSS設計を考えてみた。

2021/03/13に公開

修正 (2019/09/14)
--はクラスの命名規約的に NG だったため Modifier のプレフィックスを-に修正。
(合わせて Element のプレフィックスを_に修正)
id 名/class 名に使用できる文字の種類

TL;DR

BEM のクラス名は冗長になりがちなので、html が読みづらくなる。
※さらにpostcss-nestingとも相性が良くない。。。
そこで、BEM の利点を活かしつつ html が読みやすくなるような CSS 設計を考えてみた。

そもそも BEM とは

Block:サイトを構成するパーツのこと
ElementBlockを構成するパーツの 1 つ 1 つのこと
ModifierBlockElementのバリエーションや状態の変化のためのクラス
の 3 つの構成要素からなる CSS 設計手法のこと。
参考:BEM によるフロントエンドの設計 - 基本概念とルール | CodeGrid

BEM のデメリット

クラス名が冗長になりがちなため、html が読みづらい。。。(Block がネストされると尚更)

html
<!-- BEM -->
<div class="block--Modifier">
  <div class="block__element"></div>
</div>
<div class="block">
  <div class="block__element--Modifier"></div>
</div>

Split BEM

Block, Element, Modifierの 3 つの構成要素の考え方は BEM と同じですが、クラス名が冗長にならないように、BEM をベースにクラスの命名規則とセレクタの指定方法を変更した。

Block

  • BEM と同じ
html
<!-- BEM -->
<div class="block"></div>

<!-- Split BEM -->
<div class="block"></div>
css
/* BEM */
.block {}

/* Split BEM */
.block {}

Element

  • クラス名のプレフィックスに_を付ける。
  • Blockの子要素となるようにする。
  • 可能な限り子セレクタ>を使う。
html
<!-- BEM -->
<div class="block">
  <div class="block__element"></div>
</div>

<!-- Split BEM -->
<div class="block">
  <div class="_element"></div>
</div>
css
/* BEM */
.block__element {}

/* Split BEM */
.block > ._element {}

Modifier

  • クラス名のプレフィックスに-を付ける。
  • BlockまたはElementとセットで使用する(Modifier クラス単体で使用しない。)
html
<!-- BEM -->
<div class="block--modifier">
  <div class="block__element"></div>
</div>
<div class="block">
  <div class="block__element--modifier"></div>
</div>

<!-- Split BEM -->
<div class="block --modifier">
  <div class="_element"></div>
</div>
<div class="block">
  <div class="_element -modifier"></div>
</div>
css
/* BEM */
.block--modifier {}
.block__element--modifier {}

/* Split BEM */
.block.-modifier {}
.block > ._element.-modifier {}

Example

html
<header class="header">
  <div class="_inner">
    <h1 class="_title">
      Title
    <h1>
    <nav class="_menu menu">
      <ul class="_list">
        <li class="_item">
          <a href="#" class="_link">メニュー1</a>
        </li>
        <li class="__item">
          <a href="#" class="_link -outer">メニュー2</a>
        </li>
      </ul>
    </nav>
  </div>
</header>
css
.header {}
.header > ._inner {}
.header > ._inner > ._title {}
.header > ._inner > ._menu {}

.menu {}
.menu > ._list {}
.menu > ._list > ._item {}
.menu > ._list > ._item > ._link{}
.menu > ._list > ._item > ._link.-outer{}

まとめ

BEM に慣れた人が、BlockElementModifierの考え方、命名のノウハウを活かしつつ可読性高くなるといいなと。
似たような設計にrscssがあるが、こっちはそれぞれの命名が BEM と違うので混乱しそう。

使ってみて規約の追加、修正があれば加筆してきます。

GitHubで編集を提案
株式会社ナンバーフォー

Discussion