CSS設計規則「BEM」のまとめ
この記事ではCSSの設計規則であるBEMについて記載します。
BEMとは?
CSSの設計規則でBlock
、Element
、Modifier
の3つの要素で設計していく手法です。
CSSのクラス名は特にルールを設けずに実装していると、いつか設計が破綻し、修正すると想定していない箇所に影響を及ぼすことになりかねません。一人で実装している場合は、すべて自分が把握しているので問題ないですが、複数人で実装する場合は破綻します。
そこで、BEMではBlock
、Element
、Modifier
の3つの要素に分けて設計していきます。3つの要素はそれぞれ以下のような役割になります。
Block
… コンテナのような大きなかたまりElement
… ブロック内の要素Modifier
… BlockやElementの装飾
規則
クラス名
.block__element--modifier
- BlockとElementの間はアンダースコア2つ(
__
)でつなげる - ElementとModifierの間はハイフン2つ(
--
)でつなげる - 各要素が複数の単語になる場合は、ハイフン1つ(
-
)でつなげる
ファイル名
1つのファイルに1つのBlockを定義します。1つのファイルに複数のBlockを定義するのはNGです。ファイル名は<Block名>.scss
にします。
クラス名参照を使う
ElementやModifierクラス名参照(&
)を使います。クラス名参照を使うことでBlockやElementの名称を変更する場合に1か所修正するだけで済みます。
// NG
.article {
// articleの定義
font-weight: 700;
.article__title {
// article__titleの定義
font-size: 1.8rem;
.article__title--red {
// article__title--redの定義
color: red;
}
}
}
// OK
.article {
// articleの定義
font-weight: 700;
&__title {
// article__titleの定義
font-size: 1.8rem;
&--red {
// article__title--redの定義
color: red;
}
}
}
ElementのElementはNG
article__title__author
のようにElementのElementはNGです。このような場合は、article__title
とarticle__author
に分割します。SCSSにすると以下のようになります。
// NG
.article {
font-weight: 700;
&__title {
font-size: 1.8rem;
&__author {
color: #ccc;
}
}
}
// OK
.article {
font-weight: 700;
&__title {
font-size: 1.8rem;
}
&__author {
color: #ccc;
}
}
差分のみ定義する
同じ定義を複数個所にしていると変更したい場合に、すべて変更する必要があり手間になります。共通部分は別に定義することで、重複した定義を減らすことができます。
@extend
で共通部をまとめる
@extend
を使うと共通部を共通部をまとめることができます。
// font-weightとfont-sizeが重複している
.article {
font-weight: 700;
&__title {
font-size: 1.8rem;
&--blue {
font-size: 1.8rem;
color: #00f;
}
&--red {
font-size: 1.8rem;
color: #f00;
}
}
&__author {
color: #ccc;
}
}
// @extendを使って共通部をまとめる
.article {
%__title {
font-weight: 700;
font-size: 1.8rem;
}
&__title {
@extend %__title;
&--blue {
@extend %__title;
color: #00f;
}
&--red {
@extend %__title;
color: #f00;
}
}
&__author {
color: #ccc;
}
}
@mixin
で共通部を定義し@include
で参照する
@mixin
を使うと共通部を定義しておくと、@include
した箇所でその定義を参照できます。
// colorとfont-weightが重複している
.article {
&__title {
color: #ccc;
font-weight: 700;
font-size: 1.8rem;
}
&__subtitle {
color: #ccc;
font-weight: 700;
font-size: 1.3rem;
}
&__author {
color: #ccc;
font-weight: 700;
font-size: 0.8rem;
}
}
//
.article {
@mixin article-font() {
color: #ccc;
font-weight: 700;
}
&__title {
@include article-font();
font-size: 1.8rem;
}
&__subtitle {
@include article-font();
font-size: 1.3rem;
}
&__author {
@include article-font();
font-size: 0.8rem;
}
}
シングルクラスにする
HTMLのclass属性はスペースで区切ると複数のクラスを適用することができます。これをマルチクラスといいます。BEMではこのマルチクラスを禁止しています。BEMではclass属性に指定するクラスは1~2とされています。
<!-- NG -->
<div class="article content red">
...
</div>
<!-- OK -->
<div class="article">
<div class="article__content article__content--red">
...
</div>
</div>
その他
BEMの規則というわけではありませんが、従ったほうが良いルールを以下に記載します。
JavaScriptで参照するクラスにはjs-
のプレフィックスをつける
JavaScriptでHTMLを操作する場合、classを参照して操作する場合があります。class名はCSSでもJavaScriptでも参照するので、class名を変更するとCSSにもJavaScriptの両方に影響してしまいます。
そこで、JavaScriptで参照するクラスには明示的にjs-
のプレフィックスをつけ、JavaScript専用のクラス(CSSではjs-
で始まるクラスにはスタイルをつけない)とします。
こうすることで、class名の変更の影響範囲を抑えることができます。
<!-- NG -->
<div class="toc">
...
</div>
<!-- OK -->
<div class="js-toc">
...
</div>
最後まで読んでいただきありがとうございます。
また読んでくださいませ。
そんじゃーね。