今更ながらBEMについてのまとめです。
学習コストも低く、取り入れやすいので、勤めている会社でもこちらを使用しています。
以前は、BEMとMindBEMdingはわけて読んでいた気がしますが、今ではBEMといえばMindBEMdingという感じでしょうか?
BEMについて
BEMでは基本的にclassを使用します。
そして、クラス名は、Block, Element, Modifierの3つに分けて考えます。
Blockは全体を指すもので、その要素がElement、BlockとElementそれぞれの別バージョン(色違いなど)がModifierと呼ばれます。
具体例を見てしまった方がわかりやすいと思います。
<div class="media">
<div class="media__image">
<img src="" alt="" />
</div>
<div class="media__text">
<p class="media__title">タイトル</p>
<p class="media__lead">リード文</p>
</div>
</div>
記事の一覧などで、画像とタイトルなどが表示されているものを想像していただければと思います。
まず、media
というBlock名をつけます。
あとはこれを元に、クラス名をつけていきます。
Elementは__
(アンダースコア2つ)でつなぎ、Modifier
は--
(ハイフン2つ)でつなぎます。
例えば、画像を表示する要素は、media
というBlockのElement(要素)なので、media__image
となります。
ただ、ここにはModifierがでてきていません。
仮に、「新着記事の場合、背景色を変えよう」などといった場合に、Modifierの出番です。
下記のようにします。
<div class="media media--new">
<div class="media__imageBox">
<img src="" alt="" />
</div>
<div class="media__textBox">
<p class="media__title">タイトル</p>
<p class="media__lead">リード文</p>
</div>
</div>
<div class="media media--new">
以外は全く同じです。
ここでは、BlockのModifier(色違い)ですが、Elementの場合も同様に対応します。
media__title
の別バーションがあれば、media__title--○○
となります。
ただし、可能な限りCSSに依存した名前はつけない方がいいです。
media--red
とかにして、後から色が青に変わったら意味わからないことになります。
(css設計ではよく言われていることですが、これってとても難しいんですよね…)
また、ここはいろいろ意見があるところですが、僕はBlock__Element__Element
というような多重階層(?)は避けるようにしています。
各Elementは全てBlockの要素で、重要なのはこの親子関係と考えているからです。
では次に、これをSass(scss)で書いていきます。
Sass(scss)
まずセレクタを一通り書いてしまおうと思います。
こんな感じになります。
.media {
$block: &;
&--new {}
&__imageBox {}
&__textBox {}
&__title {
#{$block}--new & {}
}
}
好みがあるかもしれませんが、$block: &;
のように、そのときの状態を変数にいれてしまうのが好きです。
常にやる必要は全くないですが、下記のような時はやった方がいいと思います。
例えば、新着記事(media--new
)のとき、背景以外にもmedia__title
の見た目も変えて欲しいという要望があったとします。
下記のように<p class="media__title media__title--new">タイトル</p>
とするのは、ちょっと嫌ですよね?
<div class="media media--new">
<div class="media__imageBox">
<img src="" alt="" />
</div>
<div class="media__textBox">
<p class="media__title media__title--new">タイトル</p>
<p class="media__lead">リード文</p>
</div>
</div>
では、これはやめてsass側で対応しようとします。
media--new
の中にmedia__title
を入れてしまうと、media--new__title
になってしまうのでこれはダメです。
.media {
&--new {
&__title {}
}
&__title {}
}
では、&
をやめて見ましょう。
こんな感じになります。
.media {
&--new {
.media__title {}
}
&__title {}
}
他にも、下記のように&
を後ろにつけて、詳細度をあげる方法もあります。
.media {
&--new {}
&__title {
.media--new & {}
}
}
ただ、どちらも.media
という部分が重複してしまいます。
変数に代入しても同じだろと思うかもしれませんが、これがいくつもでてくることになると違ってきます。
ということで、こういったときは変数にいれてあげるのがいいと思っています。
まとめ
今更ではありますが、BEMについてまとめてみました。
個人的にお伝えしたかったのは、Block__Element__Element
というような多重階層(?)は避けるようにしよう、scssは&
を上手く使おうということでした。