
今回は今さら聞けないBEMの基本ということで、CSS設計にまつわるエントリです。
「この要素にはなんてクラス名をつけたらいいんだ・・・」という悩みはWebコーダーが必ずぶつかる課題だと思います。
その時は自分流のルールでいいかもしれませんが、後で編集するときやチームメンバーに読んでもらう時にわかりにくくなってしまうこともしばしば・・・。
だから、命名規則には広く普及しているCSS設計思想を流用するのがいいんです。
制作会社ではBEMや他の設計思想をベースにしたコーディング規約が設定されていることも珍しくないでしょう。
今回は初心者向けにBEMという命名規則の基本をご紹介します。
BEMとは
CSS設計思想にはOOCSS、BEM、SMACSS、MCSS、FLOCSS、FLOUなどいくつかありますが、その中でもBEMはクラス命名規則として後続のCSS設計思想に取り込まれている有名なものです。
正確にはBEMの発展系であるMindBEMdingというのが有名なようなのですが、英語なのでBEMについて書いているブログ等を参照した方が早いかもしれません。
BEMはBlock、Element、Modifierの頭文字を表しており、UIパーツの塊をBlockという起点にして、その構成要素をElementで、バージョン違いなどをModifierで示します。
BEMの特徴にして利点は、このBlock、Element、Modifierを1つのクラス名の中で表現するところにあるのですが、文章だけだとわからないと思うのでさっそく例を見てみましょう。
さっそく例を見てみましょう
以下が基本形です。
<div class="block"> <span class="block__element"></span> </div>
- 基本的にidは使わず、classで指定します。
- blockはUIパーツの塊(起点)を示します。
- elementはblockの構成要素を示します。
- blockとelementはアンダーバー2つで繋ぎます。
バージョン違いなどは以下のようにクラスを追記します。
<div class="block block--modifier"> <span class="block__element block__element--modifier"></span> </div>
- modifierはバージョン違いや一時的な状態を示します。
- modifierはハイフン2つで繋ぎます。
- modifierはblockにもelementにもつけてOKです。
文章だと小難しいことが書いてありましたが、実際に見てみると簡単だと思いませんか?
文字の区切りはハイフン1つ
<div class="primary-block"> <span class="primary-block__element"></span> </div>
blockとelementの塊がわかりやすくなるため、接続はアンダーバー2つなんですね。
elementのネストは禁止
よくやってしまうアンチパターンとして、elementのネストがあります。
//ダメなパターン
<div class="block">
<ul class="block__list">
<li class="block__list__item"></li>
</ul>
</div>
やっていしまいたくなる気持ちはわかりますが、elementの依存関係が複雑になっていくためアンチパターンとされています。 正しい方法としては2通りあげられます。状況に応じて使い分けてください。
//正しいパターン1
<div class="block">
<ul class="block__list">
<li class="block__list-item"></li> //blockの構成要素として
</ul>
</div
正しいパターン1のようにelementの中に同じレベルのelementが入るのはOKです。
この場合、listはblockの外で再利用することはできません。
//正しいパターン2
<div class="block">
<div class="block__list">
<ul class="list">
<li class="list__item"></li> //listの構成要素として
</ul>
</div>
</div
また、正しいパターン2のようにblockの中に別のblockが入るのもOKです。
この場合、listはblockの外でも同様のUIパーツとして再利用できます。 (そのようにCSSを設計すべきです)
elementはblock内にしか存在できない
//ダメなパターン
<div class="block">
<ul class="primary__list"> //突然primary__listが登場している
<li class="primary__list-item"></li>
</ul>
</div>
起点となるblockがないelementは存在してはいけません。
//これもやめましょう
<div class="primary">
<div class="secondary">
<span class="primary__child"></span> //secondaryの中にprimary__child
</div>
</div>
起点となるblockが直近のblockの外側にあるのも依存関係が複雑になるのでやめましょう。
バージョン違いをmodifierで表す方法
modifierはblockやelementのバージョン違いを示しますが、曖昧な概念で使い方も難しいので、チームで制作する場合は使い方について共通認識が必要です。
ここではmodifierの使い方をの一例をSCSSで紹介します。
この例ではSCSSの&を使ってセレクタのネストを実現していますが、&を使ったネストはアンチパターンという話もあるので注意してくださいね。
//HTML <div class="button button--red"> <a class="button__link">button</a> <span class="button__ornament"></span> </div>
//SCSS
.button {
$this: &; //.buttonを$thisに退避しておく
// ...
&--red { //&を使ってmodifierを付加
// redバージョン
}
&__link {
// ...
#{$this}--red & { //退避した.buttonを使う
// redバージョン
}
}
&__ornament {
// ...
#{$this}--red & { //退避した.buttonを使う
// redバージョン
}
}
}
//CSS
.button {
// ...
}
.button--red {
// ...
}
.button__link {
// ...
}
.button--red .button__link{
// ...
}
.button__ornament {
// ...
}
.button--red .button__ornament{
// ...
}
これはあくまでも一例です。
他のやり方についてはBEMのmodifierでスタイルを切り替える時の書き方が詳しいので、読んでみると面白いかもしれません。
blockにするかelementにするか迷ったら
原則として、一つの要素に複数のブロック・エレメントを設定することは避けましょう。
そして、blockにするかelementにするか迷ったらblockにしましょう。
<section class="section">
<div class="section__inner">
<h2 class="section__title">title</h2>
<div class="section__content">
<ul class="card-container">
<li class="card">
<h3 class="card__title"></h3>
<div class="card__content">
<p class="card__image-wraper">
<img class="card__image" src="card_thumb.png" alt="">
</p>
<p class="card__text">text</p>
</div>
</li>
<li class="card"><!-- 省略 --></li>
</ul>
</div>
</div>
</section>
あくまでも一例ですが、section, card-container, cardの3ブロック登場しています。
このようにすることで、section__contentの中身を入れ替える時やcardを使い回す時に楽になります。多少divが増えてもblockが別れていた方が後の修正が楽ですので、参考にしてみてください。
まとめ
- BEMはクラスの命名規則として有名なCSS設計思想
- block__element–modifierというのがクラス名の基本構造。
- elementのネストは禁止
- elementはblock内にしか存在できない
- バージョン違いや一時的な状態はmodifierで表す、使い方には工夫が必要
- 迷ったらdivやspanを増やしてもいいのでblockにする
ここまで簡単に説明してきましたが、なんとなく理解できたでしょうか?
詳しく解説しているブログは他にもたくさんあるので、色々読んでみることをお勧めします。
それでは、よいコーディングを!