BEMとは?BEM記法のCSS設計・命名規則と他の設計との比較、BEMが生まれた背景を紹介!
はじめに
このページでは、CSSの設計手法の1つであるBEMについて、解説をしていきます。なぜBEMが生まれたのか、その背景と実際のコーディング手法、その他の設計手法との比較についても触れています。興味のある方はぜひ一度ご覧ください。
BEMとは?
BEM(ベム)とは、Block Element Modifierの略で、CSSの設計手法の1つです。Yandex社により提唱されました。ユーザーインターフェースを独立したブロックに落とし込んでいくことにより、複雑なページを簡単に、かつ素早く開発することができます。
Yandex社のBEMに関するページは以下です。
Yandex社のホームページにはBEMについて説明と特徴が書かれています。これを日本語に訳すと以下のとおりです。
BEM(Block, Element, Modifier)とは、ユーザーインターフェイスを独立したブロックに分割するウェブ開発のモジュラーアプローチである。Yandexはフロントエンド開発にBEMを使用しています。
BEMは以下を含んでいます
- ウェブサイト開発のための方法論:迅速に開発し、長期的に維持する必要のあるプロジェクトを組織するためのシンプルなガイドライン。
- BEMの推奨事項を実装するオープンソースのテクノロジーとライブラリ。
- BEMの方法論を適用するための自動化ツール。
BEMの利点
- プロフェクトの成長に合わせて、コードの構造を簡単にサポートできる
- 既存のコードを再利用できる
- ポイントごとの変更を行うことができる:デザインの更新、機能要素の追加などのコストを最小限に抑えることができる
要約すると再利用可能なCSS設計を実現して素早いコーディングができるようにするということです。
BEMが誕生した背景
CSSの誕生と問題点
CSSは1996年にW3Cによって誕生しました。
それまでは、見た目を整えるためには文書ファイル(HTMLやXML)に直接スタイルを逐一指定していました。具体的には以下のようなものがありました。
<p style="font-weight: bold; color: red;">これは赤い太字です</p>
しかし、以下のような問題点がありました。
- HTMLやXMLは本来、文書構造を表すためのファイルであるためスタイルの指定がなされているのは不適切
- 同じスタイルが複数箇所にある際に、同一の修正をするのが非常に手間である
このような問題があり、CSSが誕生しました。CSSでは、HTMLやXMLとは別のファイルにスタイルを記述することができるようになりました。また、スタイルをクラスとしてまとめることで、同じスタイルを複数箇所に適用することができるようになりました
先のコードは以下のように書き換えることができるようになりました。
<p>これは赤い太字です</p>
p {
font-weight: bold;
color: red;
}
CSSの誕生によって、文書構造とスタイルの指定のファイルを分離することには成功しました。しかし、新たにページ数が増えてくると管理しきれなくなるという新たな問題が発生してしまいました。先の例のように少ない要素数、ページ数であればこれはさほど大きな問題ではなかったのですが、ページ数が増えてくると管理しきれなくなってしまいます。また、「トップページだけ <p>
タグのサイズを大きくしよう」などと思い、CSSを変更したら、他のページの <p>
タグのサイズも変更されてしまうという問題もありました。
ホームページの肥大化と複雑化するWeb開発
一方で、年々Webサイトに求められることは複雑になってきました。CSSができた当初であればWebサイトは一般的な文書的な使われ方がなされていたのですが、コンテンツのアニメーションやユーザーの操作に応じた動的な表示など、Webサイトに求められることは多様化してきました。また、Webサイトのページ数も増えてきましたことで、HTMLを1から準備するのではなく、CMSなどのツールが用いられるようになってきました。このような背景から、Webサイトの開発は複雑化してきました。
この問題が深刻である理由の1つとして、CSSはグローバルスコープであるということが言えるでしょう。言い換えると、すべてのスタイルが干渉しうる可能性を持っているとなります。
CSSは誰でも簡単にスタイリングできるという強みがありますが、この強みが逆に干渉する可能性を高めている諸刃の剣となっているといえるでしょう。
CSS設計手法の登場
CSSの仕様に対してWeb開発が複雑になりすぎたため、CSSを書いている人たちは、CSSを書く際にルールを決めていました。しかしこのルールを決めるというのにも問題があり、
- 個人・会社レベルでのルールの違いにより、作った人(会社)でないとメンテナンスができない
- ルールがしっかりと整理できていないと開発途中ですら記述にブレが生じる
- 考えが至らず、しっかりと機能しない
などの問題がありました。
そこでこの問題を解決するために生まれたのがCSS設計です。CSS設計とは、CSSを効率的に管理するためのルールを決めることです。CSS設計には様々な種類がありますが、その中でもBEMは最も有名な設計手法の1つであり、今でも多くのWebサイトで採用されています。
CSS設計にはいくつか種類がありますが、いずれも 抽象化する、 分けるという点は共通しています。
BEM以外のCSS設計との比較
このページではBEMをメインで取り扱っていますが、CSS設計手法はBEMだけではありません。具体的には
- OOCSS
- SMACSS
- PRECSS
などがあります。このセクションではこれらの設計手法とBEMを比較をしていきます。
比較の前に大前提として どの設計手法が1番優れているなどはないということです。CSS設計は対象とするサイトの規模や構造、開発者のスキルなどによって、どの設計手法が最適かは変わってきます。そのため、どの設計手法が最適かは、そのサイトの状況によって変わってきます。あくまで特徴の比較であることをご留意ください。
BEM (Block Element Modifier)
CSSクラスの命名規則に基づいた設計手法です。Block、Element、Modifierの3つの要素でクラス名を構成することで、コンポーネントの役割と状態を明確にしています。
具体的なコード
/* Block */
.button {
display: inline-block;
border: none;
background-color: #008CBA;
}
/* Element */
.button__text {
color: white;
}
/* Modifier */
.button--large {
font-size: 18px;
padding: 16px 20px;
}
<button class="button button--large"><span class="button__text">Click me</span></button>
メリット
- CSSとHTMLの構造が明確になる
- 再利用しやすいコンポーネントを作りやすい
- 名前空間が確立されることで、スタイルの衝突を避けやすくなる
デメリット
- クラス名が長くて複雑になりがち
- 命名規則に厳密なので、学習曲線がある
OOCSS (Object-Oriented CSS)
オブジェクト指向の原則をCSSに応用した設計手法。再利用可能なクラスを作成し、スタイルの繰り返しを避けることで、メンテナンス性と拡張性を高める。
具体的なコード
/* 構造用のCSS */
/* 構造と見た目を分離 */
.box {
float: left;
width: 100px;
}
/* 見た目用のCSS */
.skin {
background-color: blue;
border: 1px solid black;
}
<div class="box skin"></div>
メリット
- コードの重複が少なくなる。
- クラスが再利用しやすくなる。
- スタイルシートがより読みやすくなる。
デメリット
- CSSとHTMLのクラス名が複雑になることがある。
- 大規模なプロジェクトでは管理が難しくなることがある。
SMACSS (Scalable and Modular Architecture for CSS)
大規模なCSSの管理を容易にするために考案された、スタイルガイド。カテゴリ分けされたスタイルルールに従うことで、拡張しやすく保守しやすいCSSを作ることを目的としている。
具体的なコード
/* Base */
a {
color: #039;
}
/* Layout */
.l-header {
margin-bottom: 50px;
}
/* Module */
.tab { ... }
.tab--active { ... }
/* State */
.is-hidden {
display: none;
}
/* Theme */
.theme-ocean .tab { ... }
メリット
- CSSルールが明確にカテゴリ分けされる。
- 拡張性が高く、大規模プロジェクトに適している。
- スタイルの一貫性を保ちやすい。
デメリット
- 初期の設計に時間がかかる。
- 柔軟性が制限される場合がある。
PRECSS
SassのようなCSSプリプロセッサの機能を利用してCSSの効率的な管理を実現する。変数、ネスト、ミックスインなどの機能を使用して、CSSをより動的に記述する。
具体的なコード
$primaryColor: #333;
.button {
background: $primaryColor;
&--big {
padding: 10px 20px;
}
&__text {
color: #fff;
}
}
/* コンパイル後のCSS */
.button {
background: #333;
}
.button--big {
padding: 10px 20px;
}
.button__text {
color: #fff;
}
メリット
- 変数やネストを利用することでコードが読みやすくなる。
- より少ないコードで多様なスタイルを表現できる。
- コンパイラによるエラーチェックが利用できる。
デメリット
- プリプロセッサが必要なので開発環境の設定が必要。
- コンパイル時間がかかることがある。
- プリプロセッサ特有の機能に依存しすぎると、純粋なCSSから遠ざかる。
BEMのコーディング
上の比較のセクションでも軽く触れましたが、このセクションではより詳しくBEMのコーディングルールについて触れていきます。ここで触れるのはBEMの基本中の基本であるため更にくわしく知りたい方は、公式ドキュメントを参照してください。
BEMはその名の通り、モジュールを
- Block
- Element
- Modifier
という単位で分解、定義をしています。
BEMの命名規則
BEMでは標準の命名規則として以下のように定められています。
block-name__elem-name_mod-name_mod-val
テキストで説明をすると、
- 小文字の英数字のみを使用
- ElementとModifierはBlockの名前を継承
- それぞれの区切り(`block-name`や`elem-name`)の中に複数単語がある場合はハイフン1つでつなげる
- BlockとElementはアンダースコア(_)2つでつなげる
- Modifierのキーの区切りはアンダースコア1つ
- Modifierの値の区切りもアンダースコア1つ
次に、Block、Element、Modifierのそれぞれについて説明をしていきます。
Blockの基本
BEMにおけるBlockとは、「論理的かつ機能的に独立したページモジュール」です。具体的にはヘッダーやフッターなどが該当します。どこでも使い回すことのできるパーツという認識で問題ないと思います。
どこでも使い回せるように、Block自体にはレイアウトに関するスタイリング(例: margin
, position
)をすることは禁止されています。
クラス名は、それが何なのかを表すようにします。見た目を表すような命名は適切ではありません。具体的には以下のとおりです。
<!-- 見た目を表すような命名のため不適切 -->
<a class="text-blue">...</a>
<!-- リンクであることを表しているため適切 -->
<a class="link">...</a>
Elementの基本
Elementは、Blockを構成し、Blockの外では独立して使用できないものです。具体的には、メニュー(ここでは ul
タグがBlockに相当)の中にある li
要素や a
要素などが該当します。
Elementのクラス名はBlockのクラス名を継承しアンダースコア2つを記述したあとにElement名が来ます。 block-name__elem-name
という形になります。
具体的には以下のようになります。
<ul class="menu"> <!-- Block -->
<li class="menu__item"> <!-- Element -->
<a class="menu__link">...</a> <!-- Element -->
</li>
<li class="menu__item">
<a class="menu__link">...</a>
</li>
</ul>
Elementの命名において、気をつける点としてElementの中にElementが入る際に、親要素のElementのクラス名を継承しないようにするということです。先のコードで言うと以下のようになります。
<ul class="menu">
<li class="menu__item">
<a class="menu__link">...</a>
</li>
</ul>
<!-- 不適切な例 -->
<ul class="menu">
<li class="menu__item">
<a class="menu__item__link">...</a>
</li>
</ul>
理由としては、
- Block内でElementの移動が生じる可能性がある
- 親要素のElementがない状態で使うことがある
- 逆に親要素にElementを追加する可能性もある
などがあります。上記の理由により、CSSを記述する際にも子セレクターは使用しません。
/* 子セレクターを使っているため不適切 */
.menu {...}
.menu .menu__item {...}
.menu .menu__item .menu__item__link {...}
/* 子セレクターを使っていないので適切 */
.menu {...}
.menu__item {...}
.menu__item__link {...}
Modifierの基本
Modifierは、「BlockまたはElementの状態や見た目、振る舞いなどを定義するもの」です。BlockやElementに対するオプション的な位置づけなので必須というわけではありません。
Modifierはオプション的位置づけなので単独で使用することはできず、必ずBlockかElementのクラス名のある状態で二つ目以降のクラス名として使います。具体的には以下のとおりです。
<!-- 単独使用なので不適切 -->
<button class="button_size_s">...</button>
<!-- 適切 -->
<button class="button button_size_s">...</button>
Modifierの命名は、 それがどうであるか ということを重視します。具体的には以下のようです。
- 見た目:どんなサイズなのか、色かなど
size_s
:サイズが小さいcolor_red
:赤色
- 状態:他のブロックと比べどうなのか
disabled
:利用不可、無効になっているactived
:(タブなど)選択されている
- 振る舞い:どう動くのか
directions_right-to-left
:右から左へ動く
など
まとめ
いかがでしたでしょうか。今回は、CSS設計手法の1つであるBEMについて、他の設計手法との比較や誕生の背景などを説明しました。
BEMを使うことでHTMLコーディング時からクラス名で迷うことが少なくなり、コーディングにかかる時間が短縮したと感じます。また、CSSの管理がしやすくなるため、メンテナンス性も高まります。
個人的には1番おすすめのCSS設計手法です。ぜひ、BEMを使ってみてください!!