今回は今さら聞けない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にする
ここまで簡単に説明してきましたが、なんとなく理解できたでしょうか?
詳しく解説しているブログは他にもたくさんあるので、色々読んでみることをお勧めします。
それでは、よいコーディングを!