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

3 min read読了の目安(約2800字

修正 (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と違うので混乱しそう。

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