はじめに#
CSSの開発において「同じクラス名を使ってしまい、意図しない箇所のスタイルが崩れた」「クラス名から役割がわからず、修正箇所を特定するのに時間がかかった」といった経験はないでしょうか。
これらの問題を解決するのがBEM(Block Element Modifier)記法です。BEMは、Yandex社が開発した命名規則で、Google、BBC、JetBrainsなど世界中の企業で採用されています。
本記事では、BEM記法を基礎から実践まで体系的に解説します。
- BEM記法の基本概念(Block、Element、Modifier)
- BEMの命名ルールと記法パターン
- 実践的なコンポーネント設計手法
- BEMのメリットと注意点
- よくあるアンチパターンと対処法
前提条件#
本記事を読み進めるにあたり、以下の知識があることを前提としています。
- CSSの基本構文(セレクタ、プロパティ、値の関係)
- CSSセレクタ(要素、クラス、ID、属性セレクタ)の使い方
- CSSの詳細度とカスケードの基礎知識
CSS設計の基本原則については、CSS設計の基本原則 - 保守性の高いスタイルを書くためにを参照してください。
動作確認環境#
- Google Chrome 131以降
- Firefox 133以降
- Safari 18以降
- Microsoft Edge 131以降
BEM記法とは#
BEMの3つの構成要素#
BEMは「Block」「Element」「Modifier」の頭文字を取った命名規則です。UIを3つの概念に分解し、それぞれに明確な役割を持たせることで、予測可能で再利用しやすいCSSクラスを設計できます。
graph TD
A[BEM記法] --> B[Block<br/>独立したコンポーネント]
A --> C[Element<br/>Blockを構成する要素]
A --> D[Modifier<br/>状態やバリエーション]
B --> E["例: .card, .button, .nav"]
C --> F["例: .card__title, .button__icon"]
D --> G["例: .card--featured, .button--large"]Block(ブロック)#
Blockは、単独で意味を持つ独立したコンポーネントです。ヘッダー、ナビゲーション、カード、ボタンなど、再利用可能なUI部品がBlockに該当します。
1
2
3
4
5
6
|
/* Blockの例 */
.header { }
.navigation { }
.card { }
.button { }
.search-form { }
|
Blockは以下の特徴を持ちます。
| 特徴 |
説明 |
| 独立性 |
他のBlockに依存せず、単独で機能する |
| 再利用性 |
ページ内の任意の場所に配置できる |
| ネスト可能 |
Block内に別のBlockを含められる |
1
2
3
4
5
6
7
8
9
10
11
|
<!-- Blockは単独で意味を持つ -->
<nav class="navigation">
<!-- 中身は後で追加 -->
</nav>
<!-- Blockは他のBlock内にネストできる -->
<header class="header">
<nav class="navigation">
<!-- navigationはheaderに依存しない独立したBlock -->
</nav>
</header>
|
Element(エレメント)#
Elementは、Blockを構成する要素で、Block外では意味を持たない部品です。Elementは必ず特定のBlockに属し、Block名とElement名をダブルアンダースコア(__)で接続して表現します。
1
2
3
4
5
6
|
/* 構文: block__element */
.card__title { }
.card__image { }
.card__content { }
.navigation__item { }
.navigation__link { }
|
Elementの特徴は以下のとおりです。
| 特徴 |
説明 |
| 従属性 |
必ず特定のBlockに属する |
| 意味の限定 |
Block外では単独で使用できない |
| フラット構造 |
Element同士のネストは命名に反映しない |
1
2
3
4
5
6
|
<!-- Elementは必ずBlock内に配置 -->
<article class="card">
<img class="card__image" src="thumbnail.jpg" alt="サムネイル">
<h2 class="card__title">記事タイトル</h2>
<p class="card__content">記事の概要です。</p>
</article>
|
Modifier(モディファイア)#
Modifierは、BlockやElementの見た目・状態・振る舞いを変更するフラグです。Block名またはElement名とModifier名をダブルハイフン(--)で接続して表現します。
1
2
3
4
5
6
7
8
|
/* Block Modifier: block--modifier */
.button--primary { }
.button--large { }
.card--featured { }
/* Element Modifier: block__element--modifier */
.card__title--highlighted { }
.navigation__link--active { }
|
Modifierには2種類のタイプがあります。
| タイプ |
説明 |
例 |
| Boolean |
存在の有無で状態を表す |
--disabled, --active, --hidden |
| Key-Value |
値を持つバリエーション |
--size-large, --theme-dark, --color-red |
1
2
3
4
5
6
7
|
<!-- Boolean Modifier -->
<button class="button button--disabled">無効なボタン</button>
<!-- Key-Value Modifier -->
<button class="button button--size-large button--theme-primary">
大きなプライマリボタン
</button>
|
BEMの命名ルール#
基本構文#
BEMの命名規則は以下の構文に従います。
block-name__element-name--modifier-name
各パーツの接続ルールをまとめると以下のようになります。
graph LR
A[block-name] -->|"__"| B[element-name]
A -->|"--"| C[modifier-name]
B -->|"--"| D[element-modifier]
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#f3e5f5
style D fill:#f3e5f5詳細な命名ルール#
BEMの命名において守るべきルールは以下のとおりです。
| ルール |
説明 |
例 |
| 小文字のみ使用 |
大文字は使用しない |
searchForm → search-form |
| 単語はハイフンで接続 |
複合語はハイフンで区切る |
mainnavigation → main-navigation |
Elementは__で接続 |
ダブルアンダースコアを使用 |
card__title |
Modifierは--で接続 |
ダブルハイフンを使用 |
button--primary |
命名スタイルのバリエーション#
BEMにはいくつかの命名スタイルが存在します。本記事では最も一般的な「Two Dashes style」を採用していますが、プロジェクトによっては他のスタイルを採用することもあります。
1
2
3
4
5
|
/* Two Dashes style(本記事で採用) */
.block-name__element-name--modifier-name { }
/* 例 */
.search-form__input--disabled { }
|
1
2
3
4
5
|
/* Classic style(元祖BEM) */
.block-name__element-name_modifier-name { }
/* 例 */
.search-form__input_disabled { }
|
1
2
3
4
5
|
/* CamelCase style */
.blockName-elemName_modName { }
/* 例 */
.searchForm-input_disabled { }
|
プロジェクト内では一貫したスタイルを使用することが重要です。チームで開発する場合は、どのスタイルを採用するか事前に合意しておきましょう。
実践的なコンポーネント設計#
カードコンポーネントの設計#
実際のUIコンポーネントをBEMで設計してみましょう。以下は、ブログ記事のカードコンポーネントの例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<article class="article-card article-card--featured">
<div class="article-card__thumbnail">
<img
class="article-card__image"
src="/images/thumbnail.jpg"
alt="記事のサムネイル"
>
<span class="article-card__category">技術記事</span>
</div>
<div class="article-card__body">
<h2 class="article-card__title">BEM記法入門ガイド</h2>
<p class="article-card__excerpt">
BEMの命名規則を使って保守性の高いCSSを書く方法を解説します。
</p>
<div class="article-card__meta">
<time class="article-card__date">2026-01-05</time>
<span class="article-card__author">山田太郎</span>
</div>
</div>
<a class="article-card__link" href="/posts/bem-guide/">続きを読む</a>
</article>
|
対応するCSSは以下のようになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
/* Block */
.article-card {
display: flex;
flex-direction: column;
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
/* Block Modifier */
.article-card--featured {
border: 2px solid #3b82f6;
}
/* Elements */
.article-card__thumbnail {
position: relative;
aspect-ratio: 16 / 9;
}
.article-card__image {
width: 100%;
height: 100%;
object-fit: cover;
}
.article-card__category {
position: absolute;
top: 8px;
left: 8px;
padding: 4px 8px;
background-color: #3b82f6;
color: #ffffff;
font-size: 12px;
border-radius: 4px;
}
.article-card__body {
padding: 16px;
flex: 1;
}
.article-card__title {
margin: 0 0 8px;
font-size: 18px;
font-weight: 700;
line-height: 1.4;
}
.article-card__excerpt {
margin: 0 0 12px;
color: #6b7280;
font-size: 14px;
line-height: 1.6;
}
.article-card__meta {
display: flex;
gap: 16px;
font-size: 12px;
color: #9ca3af;
}
.article-card__date { }
.article-card__author { }
.article-card__link {
display: block;
padding: 12px 16px;
background-color: #f3f4f6;
color: #3b82f6;
text-align: center;
text-decoration: none;
font-weight: 500;
transition: background-color 0.2s;
}
.article-card__link:hover {
background-color: #e5e7eb;
}
|
ナビゲーションコンポーネントの設計#
複数の状態を持つナビゲーションコンポーネントの例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<nav class="main-nav">
<ul class="main-nav__list">
<li class="main-nav__item">
<a class="main-nav__link main-nav__link--active" href="/">
ホーム
</a>
</li>
<li class="main-nav__item">
<a class="main-nav__link" href="/about/">
このサイトについて
</a>
</li>
<li class="main-nav__item main-nav__item--has-dropdown">
<a class="main-nav__link" href="/categories/">
カテゴリ
</a>
<ul class="main-nav__dropdown">
<li class="main-nav__dropdown-item">
<a class="main-nav__dropdown-link" href="/categories/frontend/">
フロントエンド
</a>
</li>
<li class="main-nav__dropdown-item">
<a class="main-nav__dropdown-link" href="/categories/backend/">
バックエンド
</a>
</li>
</ul>
</li>
</ul>
</nav>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
/* Block */
.main-nav {
background-color: #1f2937;
}
/* Elements */
.main-nav__list {
display: flex;
gap: 4px;
margin: 0;
padding: 0 16px;
list-style: none;
}
.main-nav__item {
position: relative;
}
.main-nav__item--has-dropdown:hover .main-nav__dropdown {
display: block;
}
.main-nav__link {
display: block;
padding: 16px 12px;
color: #d1d5db;
text-decoration: none;
transition: color 0.2s;
}
.main-nav__link:hover {
color: #ffffff;
}
/* Element Modifier */
.main-nav__link--active {
color: #ffffff;
border-bottom: 2px solid #3b82f6;
}
.main-nav__dropdown {
display: none;
position: absolute;
top: 100%;
left: 0;
min-width: 180px;
margin: 0;
padding: 8px 0;
background-color: #374151;
border-radius: 0 0 4px 4px;
list-style: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.main-nav__dropdown-item { }
.main-nav__dropdown-link {
display: block;
padding: 8px 16px;
color: #d1d5db;
text-decoration: none;
}
.main-nav__dropdown-link:hover {
background-color: #4b5563;
color: #ffffff;
}
|
フォームコンポーネントの設計#
入力フォームのバリデーション状態を含むコンポーネントの例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
<form class="contact-form">
<div class="contact-form__group">
<label class="contact-form__label" for="name">
お名前
<span class="contact-form__required">必須</span>
</label>
<input
class="contact-form__input"
type="text"
id="name"
name="name"
placeholder="山田太郎"
>
</div>
<div class="contact-form__group contact-form__group--error">
<label class="contact-form__label" for="email">
メールアドレス
<span class="contact-form__required">必須</span>
</label>
<input
class="contact-form__input contact-form__input--error"
type="email"
id="email"
name="email"
placeholder="example@example.com"
>
<span class="contact-form__error-message">
有効なメールアドレスを入力してください
</span>
</div>
<div class="contact-form__group">
<label class="contact-form__label" for="message">
お問い合わせ内容
</label>
<textarea
class="contact-form__textarea"
id="message"
name="message"
rows="5"
></textarea>
</div>
<div class="contact-form__actions">
<button class="contact-form__button contact-form__button--primary" type="submit">
送信する
</button>
<button class="contact-form__button contact-form__button--secondary" type="reset">
クリア
</button>
</div>
</form>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
/* Block */
.contact-form {
max-width: 600px;
padding: 24px;
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Elements */
.contact-form__group {
margin-bottom: 20px;
}
.contact-form__group--error .contact-form__input,
.contact-form__group--error .contact-form__textarea {
border-color: #ef4444;
}
.contact-form__label {
display: block;
margin-bottom: 6px;
font-weight: 500;
color: #374151;
}
.contact-form__required {
margin-left: 4px;
padding: 2px 6px;
background-color: #ef4444;
color: #ffffff;
font-size: 11px;
border-radius: 2px;
}
.contact-form__input,
.contact-form__textarea {
width: 100%;
padding: 10px 12px;
border: 1px solid #d1d5db;
border-radius: 4px;
font-size: 16px;
transition: border-color 0.2s, box-shadow 0.2s;
}
.contact-form__input:focus,
.contact-form__textarea:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
}
.contact-form__input--error {
border-color: #ef4444;
}
.contact-form__input--error:focus {
border-color: #ef4444;
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.2);
}
.contact-form__error-message {
display: block;
margin-top: 4px;
color: #ef4444;
font-size: 13px;
}
.contact-form__textarea {
resize: vertical;
min-height: 120px;
}
.contact-form__actions {
display: flex;
gap: 12px;
margin-top: 24px;
}
.contact-form__button {
padding: 12px 24px;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s;
}
.contact-form__button--primary {
background-color: #3b82f6;
color: #ffffff;
}
.contact-form__button--primary:hover {
background-color: #2563eb;
}
.contact-form__button--secondary {
background-color: #e5e7eb;
color: #374151;
}
.contact-form__button--secondary:hover {
background-color: #d1d5db;
}
|
BEMのメリット#
予測可能性の向上#
BEMを使用することで、クラス名から以下の情報を即座に読み取れます。
graph LR
A[".article-card__title--highlighted"] --> B["Block: article-card"]
A --> C["Element: title"]
A --> D["Modifier: highlighted"]
B --> E["独立したカードコンポーネント"]
C --> F["カードのタイトル部分"]
D --> G["強調表示状態"]この予測可能性により、以下のメリットが得られます。
| メリット |
説明 |
| コードの理解が容易 |
クラス名を見ただけで役割がわかる |
| 検索性の向上 |
Block名で関連するスタイルを検索できる |
| 影響範囲の把握 |
変更がどこに影響するか予測できる |
詳細度の統一#
BEMでは、すべてのセレクタがクラスセレクタ1つで構成されるため、詳細度が均一になります。
1
2
3
4
5
6
7
8
9
10
|
/* BEMを使用した場合: すべて詳細度 0-1-0 */
.button { }
.button--primary { }
.button__icon { }
.navigation__link--active { }
/* BEMを使用しない場合: 詳細度がバラバラ */
#header .nav a { } /* 1-1-1 */
.container .button { } /* 0-2-0 */
nav ul li a.active { } /* 0-1-4 */
|
詳細度が統一されることで、以下の問題を回避できます。
!importantの多用
- 詳細度を上げるためのセレクタの複雑化
- スタイルの上書きが困難になる「詳細度戦争」
再利用性とモジュール性#
Blockは独立したコンポーネントとして設計されるため、他のページやプロジェクトへの移植が容易です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/* このBlockは他のプロジェクトにそのままコピーできる */
.tag {
display: inline-block;
padding: 4px 8px;
background-color: #e5e7eb;
border-radius: 4px;
font-size: 12px;
}
.tag--primary {
background-color: #3b82f6;
color: #ffffff;
}
.tag--danger {
background-color: #ef4444;
color: #ffffff;
}
|
自己文書化されたコード#
BEMのクラス名は、それ自体がドキュメントの役割を果たします。
1
2
3
4
5
6
7
8
9
10
11
12
|
<!-- クラス名から構造と状態がわかる -->
<div class="modal modal--open">
<div class="modal__overlay"></div>
<div class="modal__content">
<h2 class="modal__title">確認</h2>
<p class="modal__body">この操作を実行しますか?</p>
<div class="modal__actions">
<button class="modal__button modal__button--confirm">はい</button>
<button class="modal__button modal__button--cancel">いいえ</button>
</div>
</div>
</div>
|
BEMの注意点とアンチパターン#
クラス名が長くなる問題#
BEMの最大の懸念点は、クラス名が長くなりがちなことです。
1
2
|
/* 長すぎるクラス名の例 */
.user-profile-card__social-media-links__twitter-icon--highlighted { }
|
この問題への対処法は以下のとおりです。
- Block名を簡潔にする:
user-profile-card → profile-card または user-card
- 深いネストは新しいBlockに切り出す: 後述の「Elementのネスト問題」を参照
Elementのネスト問題#
BEMでは、Element内のElementを__で連結しません。これはBEMの重要なルールです。
1
2
3
4
5
6
7
8
9
10
|
/* 悪い例: Element内のElementを連結 */
.card__header__title { }
.card__body__content__paragraph { }
/* 良い例: フラットな構造を維持 */
.card__header { }
.card__title { }
.card__body { }
.card__content { }
.card__paragraph { }
|
HTMLのDOM構造がネストしていても、BEMのクラス名はフラットに保ちます。
1
2
3
4
5
6
7
8
9
10
|
<!-- DOM構造はネストしているが、クラス名はフラット -->
<article class="card">
<header class="card__header">
<h2 class="card__title">タイトル</h2>
<span class="card__category">カテゴリ</span>
</header>
<div class="card__body">
<p class="card__content">本文です。</p>
</div>
</article>
|
Blockへの切り出し判断#
コンポーネントが複雑になった場合、一部を新しいBlockとして切り出すことを検討します。
graph TD
A[Blockが複雑になったら] --> B{再利用の可能性は?}
B -->|高い| C[新しいBlockとして切り出す]
B -->|低い| D{Elementが多すぎる?}
D -->|はい| C
D -->|いいえ| E[現状維持]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!-- 切り出し前: cardに多くのElementがある -->
<article class="card">
<div class="card__author-info">
<img class="card__author-avatar" src="avatar.jpg">
<span class="card__author-name">山田太郎</span>
<span class="card__author-role">エンジニア</span>
</div>
</article>
<!-- 切り出し後: authorを独立したBlockに -->
<article class="card">
<div class="card__author">
<div class="author">
<img class="author__avatar" src="avatar.jpg">
<span class="author__name">山田太郎</span>
<span class="author__role">エンジニア</span>
</div>
</div>
</article>
|
Modifierの単独使用#
Modifierは必ず元のBlockまたはElementクラスと併用します。Modifier単独での使用は禁止です。
1
2
3
4
5
|
<!-- 悪い例: Modifierのみ -->
<button class="button--primary">ボタン</button>
<!-- 良い例: 元のクラスと併用 -->
<button class="button button--primary">ボタン</button>
|
これは、Modifierが元のスタイルを「修正」するものであり、ベースとなるスタイルが必要だからです。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/* ベーススタイル */
.button {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* Modifierはベーススタイルを上書き・拡張 */
.button--primary {
background-color: #3b82f6;
color: #ffffff;
}
|
SCSSでBEMを効率的に書く#
SCSSのネスト機能を使うと、BEMをより効率的に記述できます。
親セレクタ参照(&)の活用#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
.card {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
// Element: &__element
&__header {
padding: 16px;
border-bottom: 1px solid #e5e7eb;
}
&__title {
margin: 0;
font-size: 18px;
font-weight: 700;
// Element Modifier
&--large {
font-size: 24px;
}
}
&__body {
padding: 16px;
}
&__footer {
padding: 16px;
background-color: #f9fafb;
}
// Block Modifier
&--featured {
border: 2px solid #3b82f6;
}
&--compact {
.card__header,
.card__body,
.card__footer {
padding: 8px;
}
}
}
|
コンパイル後のCSSは以下のようになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
.card {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.card__header {
padding: 16px;
border-bottom: 1px solid #e5e7eb;
}
.card__title {
margin: 0;
font-size: 18px;
font-weight: 700;
}
.card__title--large {
font-size: 24px;
}
.card__body {
padding: 16px;
}
.card__footer {
padding: 16px;
background-color: #f9fafb;
}
.card--featured {
border: 2px solid #3b82f6;
}
.card--compact .card__header,
.card--compact .card__body,
.card--compact .card__footer {
padding: 8px;
}
|
ファイル構成の例#
BEMを採用したプロジェクトでは、Block単位でファイルを分割することが一般的です。
scss/
├── base/
│ ├── _reset.scss
│ └── _typography.scss
├── components/
│ ├── _button.scss
│ ├── _card.scss
│ ├── _form.scss
│ ├── _modal.scss
│ └── _navigation.scss
├── layouts/
│ ├── _header.scss
│ ├── _footer.scss
│ └── _sidebar.scss
└── main.scss
BEMと他の設計手法の組み合わせ#
BEMとITCSSの併用#
ITCSS(Inverted Triangle CSS)の階層構造とBEMの命名規則を組み合わせることで、より堅牢なCSS設計が可能になります。
graph TD
A[Settings<br/>変数定義] --> B[Tools<br/>ミックスイン・関数]
B --> C[Generic<br/>リセット・ノーマライズ]
C --> D[Elements<br/>素のHTML要素]
D --> E[Objects<br/>レイアウトパターン]
E --> F[Components<br/>BEMで設計したUI部品]
F --> G[Utilities<br/>ヘルパークラス]BEMとユーティリティクラスの併用#
Tailwind CSSのようなユーティリティファーストアプローチと、BEMによるコンポーネント設計を組み合わせる手法もあります。
1
2
3
4
5
|
<!-- BEMコンポーネント + ユーティリティクラス -->
<article class="card mt-4 mb-8">
<h2 class="card__title text-center">タイトル</h2>
<p class="card__content line-clamp-3">本文...</p>
</article>
|
この場合、BEMでコンポーネント固有のスタイルを定義し、ユーティリティクラスでスペーシングや配置などの汎用的なスタイルを適用します。
まとめ#
BEM記法は、CSSクラスの命名規則を統一することで、予測可能で保守性の高いスタイル設計を実現する手法です。本記事で解説した内容を振り返ります。
| 概念 |
役割 |
命名規則 |
| Block |
独立したコンポーネント |
.block-name |
| Element |
Blockを構成する要素 |
.block-name__element-name |
| Modifier |
状態やバリエーション |
.block-name--modifier |
BEMを採用することで得られる主なメリットは以下のとおりです。
- クラス名から役割と関係性が読み取れる(予測可能性)
- 詳細度が統一され、スタイルの上書きが容易(詳細度の管理)
- コンポーネント単位での再利用が可能(モジュール性)
- コード自体がドキュメントになる(自己文書化)
一方、クラス名が長くなりがちという注意点もありますが、適切なBlock分割とSCSSの活用で軽減できます。
BEMは学習コストが低く、チームへの導入も容易な設計手法です。まずは小さなコンポーネントからBEMを適用し、徐々にプロジェクト全体に広げていくことをおすすめします。
参考リンク#