l12a

白ウサギを追え

BEMの設計とコンポーネント設計の関係の話

同僚との雑談中に BEM の話題に至り、コンポーネント設計の中に現在も活かされている話をしました。

BEM

語られ尽くしたことと思いますが、いわゆる「 CSS 設計」の方法論の一つです。
他にもいくつかの有名な CSS 設計スタイルがありますが、僕は BEM を使う経験が最も多かったです。 この記事では BEM それ自体のやり方は詳しく解説しません。

getbem.com

BEM を端的に言えば、
CSS の仕様に起因するコードの複雑性」を「単一のクラスセレクタに限定すること」によって防ぎ、 「クラス名の衝突」を「クラス名を冗長にすること」によって避けるアプローチ
であると僕は考えています。

今一度考える、BEM がもたらしたもの

BEM の登場は些か前のことになるので、今となっては形式化していることも多いです。
BEM がどんな良いことをもたらしたのか、今一度思い出してみます。

UI のモジュール化

Block は他の Block からのスタイルの影響を受けません。
すでに作成した Block の単位に限っては、レイアウトを自由に変更することができ、 コンポーネントの再利用も簡単にできます。( Block を利用して UI のカタログにすることも!)

ルール

BEM は簡単且つ厳格なルールによって守られているので、個人差による解釈の違いや、例外がなく、学習コストが低いです。
またその運用においても、要素のクラス属性を見れば、コードベースのどの位置にルールが書かれているかを容易にマッピングしやすくなる点が利点です。

コンポーネント設計と BEM

昨今、コンポーネントベースのテンプレートエンジンを組み込んだプロジェクトでは、 BEM がもたらす利点と、クラス名衝突を避けるための方法がエンジンの機能によって代替可能になったことから、 BEM 命名規則を採用する機会は減ってきました。
コンポーネント分割によるモジュール化、また Vue.js であれば <style scoped> にすることでクラス名の一意性はそのコンポーネント内だけの限られた要素さえ考慮すればよくなった、といったことです。

ですが、コンポーネントの設計の考え方自体は BEM による Block の設計となんら変わっていません。

BEM によるモジュール設計

例えば BEM で設計された UI モジュールは次のようになります。

<div class="hoge">
  <p class="hoge__fuga">...</p>
  <p class="hoge__fuga--piyo">...</p>
</div>

CSS または SCSS は、以下のようになります。

.hoge {...}
.hoge__fuga {...}
.hoge__fuga--piyo {...}

SCSS の場合は、以下のようになる場合もよく見られます。

.hoge {
  ...
  &__fuga {
    ...
    &--piyo {...}
  }
}

コンポーネント設計

同じものをコンポーネントベースのテンプレートエンジンで設計するならこうなります。
Vue.js を使った場合を想定しています。
内包されるコンポーネントhoge コンポーネント側に書くことが多いですが、概念としてはこのような感じです。

<hoge>
  <fuga>...</fuga>
  <fuga :piyo="true">...</fuga>
</hoge>

CSS は各コンポーネント<style scoped> で書きますので、class 名を冗長にする必要はありません。

終わり

ギョームにおいては別のシチュエーションが考えられます。
なんらかのサーバサイドテンプレート + BEM による CSS 設計( CSS または Sass などのプリプロセッサ )といった環境から、Vue.js へのリプレースなどです。
サーバサイドテンプレートから Vue.js への分離はするが、CSS だけは Vue コンポーネントに移植する工数がないので、既存の CSS をそのまま読み込んでおく、ということもあるでしょう。
既存のコードベースの状態次第になるプロジェクトの場合はそんなにうまくいかないこともありますが、
それがどのように設計され、どう活かせるのかを見出すためには、歴史的背景(今回の話であれば、BEM)について知見を持っておいて損はないことと思います。