🤔

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

らんす🍐2021/03/12に公開

修正 (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

ログインするとコメントできます