名前の付け方——役割で名付ける
レッスン2:名前の付け方——役割で名付ける
このレッスンで学ぶこと
- 見た目に由来する名前が、なぜあとから破綻するのかを理解する
- 「見た目」ではなく「役割」で名付ける発想を身につける
- BEM(Block・Element・Modifier)という命名の考え方を理解する
- 命名の粒度と、名前が長くなることの受け止め方を身につける
前回のレッスンでは、CSS が壊れていく経過を詳細度とカスケードの視点から見ました。強さで勝とうとするほど、次はもっと強い指定が必要になるという連鎖です。今回は、CSS が壊れるもう 1 つの大きな原因である「名前の付け方」を扱います。
見た目由来の名前が破綻する理由
CSS を書き始めたばかりのころ、クラス名は見た目をそのまま表す言葉になりがちです。
.red-box {
background: #e74c3c;
padding: 16px;
border-radius: 4px;
}
.red-box という名前は、書いた瞬間はとてもわかりやすい名前です。赤い箱だから red-box。迷う余地がありません。ところが、しばらくしてデザインが変更され、背景色を青に変えることになったとします。
.red-box {
background: #3498db; /* 赤ではなくなったのに、クラス名は red-box のまま */
padding: 16px;
border-radius: 4px;
}
ここで最初の問題が生まれます。.red-box という名前と、実際の見た目(青)が一致しなくなりました。あとからこのコードを読む人は、「なぜ red-box なのに青いのか」と戸惑います。名前を変えようとしても、HTML 側の複数の場所で class="red-box" が使われていれば、すべて書き換える必要が出てきます。
もう 1 つの問題は、見た目の名前が「その見た目にしか使えない」という思い込みを生むことです。
<div class="red-box">警告メッセージです</div>
<div class="red-box">在庫が残りわずかです</div>
この 2 つは見た目こそ同じ赤い箱ですが、担当している役割はまったく違います。片方は警告、もう片方は在庫状況の通知です。役割が違うのに、名前は「色」という見た目の情報しか語っていません。
⚠️ 注意 見た目由来の名前が悪いのは、「わかりにくいから」ではありません。むしろ最初はわかりやすいのです。問題は、見た目は変わるものなのに、名前は変わらずに残り続けることです。名前と実態がずれていくことに気づきにくいのが、見た目由来の命名の本当の弱点です。
役割で名付けるという発想
見た目由来の名前の弱点を踏まえると、次の発想が見えてきます。クラス名は、その要素が何であるか(見た目)ではなく、その要素が何をしているか(役割)を表すべきだという考え方です。
先ほどの例を、役割で名付け直してみます。
<div class="alert alert--warning">警告メッセージです</div>
<div class="alert alert--stock-low">在庫が残りわずかです</div>
.alert {
padding: 16px;
border-radius: 4px;
}
.alert--warning {
background: #f39c12;
}
.alert--stock-low {
background: #e74c3c;
}
.alert という名前は、「これは警告や通知を表示する部品である」という役割を語っています。背景色が変わっても、警告の種類が増えても、.alert という名前そのものは揺らぎません。デザインが変わったときに書き換える必要があるのは色の値だけで、クラス名を追いかけて HTML を直す作業は発生しません。
役割で名付けると、名前を見ただけでその要素の目的がわかるようになります。.card、.button、.nav、.form-field といった名前は、見た目の詳細を語らない代わりに、「これは何のための部品か」を明確に語ります。
中核メッセージ 3:名前は見た目ではなく役割で付けます。見た目はデザインの都合で変わりますが、役割はよほどの設計変更がない限り変わりません。
💡 ポイント 役割で名付けるかどうかを判断する簡単な方法があります。「このクラス名は、デザインが変わったあとも意味が通じるか」を自問することです。
.red-boxは色が変わった瞬間に意味を失いますが、.alertは色がいくつ変わっても意味を保ち続けます。
BEM という命名の考え方
役割で名付けるという発想を、具体的な記法にまで落とし込んだ命名の考え方の 1 つに BEM があります。BEM は Block(塊)・Element(要素)・Modifier(修飾子)という 3 つの単位で名前を組み立てる考え方です。
Block——独立した部品のかたまり
Block は、それ単体で意味を持つ独立した部品です。カード、ナビゲーション、フォームなどが Block にあたります。
.card {
border: 1px solid #ddd;
border-radius: 4px;
padding: 16px;
}
Element——Block の中の構成要素
Element は、Block の内部を構成する部品で、Block から独立しては意味を持ちません。記法は Block__Element のように、アンダースコア 2 つでつなぎます。
<div class="card">
<h3 class="card__title">商品名</h3>
<p class="card__price">1,980円</p>
<button class="card__button">カートに入れる</button>
</div>
.card__title {
font-size: 18px;
font-weight: bold;
}
.card__price {
color: #e74c3c;
}
.card__button {
padding: 8px 16px;
}
.card__title は「カードの中のタイトル」という役割を、名前だけで伝えています。.card というかたまりの外に置かれた <h3> にこの名前を付けても意味が通じないという点が重要です。Element の名前は、常に自分が属する Block とセットで意味を持ちます。
Modifier——見た目や状態のバリエーション
Modifier は、Block や Element に見た目や状態のバリエーションを加えるための単位です。記法は Block--Modifier のように、ハイフン 2 つでつなぎます。
<div class="card card--featured">
<h3 class="card__title">おすすめ商品</h3>
</div>
.card--featured {
border-color: #f39c12;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.card--featured は「注目カードというバリエーション」を表しています。ベースになる .card のスタイルはそのまま活かしつつ、追加のスタイルだけを .card--featured に書き足す形になります。
flowchart TD
A[Block<br/>card] --> B[Element<br/>card__title]
A --> C[Element<br/>card__price]
A --> D[Modifier<br/>card--featured]
B --> E[役割:カードの中のタイトル]
D --> F[役割:カードの見た目バリエーション]
この図は、1 つの Block から Element と Modifier がどのように分岐するかを表しています。Element は Block の内部構造を、Modifier は Block や Element のバリエーションを表すという役割分担が見て取れます。
📝 補足 BEM はいくつかの制作現場で使われてきた命名の考え方の 1 つで、唯一の正解ではありません。大切なのは、アンダースコアやハイフンの記法そのものではなく、「Block・Element・Modifier という 3 つの役割に分けて考える」という発想です。この発想は、記法が違う別の命名ルールを使う場合にも応用できます。
セレクタを組み合わせず、クラス名だけで完結させる
BEM の考え方には、もう 1 つ大事な前提があります。それは、セレクタを深くネストせず、クラス名 1 つだけで見た目を確定させるという前提です。
/* 避けたい書き方:ネストに依存している */
.card .title {
font-size: 18px;
}
/* BEM の書き方:クラス名だけで完結している */
.card__title {
font-size: 18px;
}
.card .title という書き方は、.card の中に .title が置かれているという「位置関係」に依存しています。この .title を別の場所に移動すると、スタイルが外れてしまうかもしれません。一方、.card__title は単一のクラスセレクタなので、どこに置いても同じスタイルが適用されます。これは、レッスン1 で扱った詳細度の話ともつながります。単一のクラスセレクタだけで組み立てれば、詳細度は常に均一(クラス 1 個分)に保たれ、!important に頼る必要も減ります。
命名の粒度——どこまで細かく分けるか
BEM の考え方を知ると、次に悩むのが「どこまで Element を分けるべきか」という粒度の問題です。
分けすぎると、次のようになります。
<div class="card">
<div class="card__header">
<div class="card__header-inner">
<h3 class="card__header-inner-title">商品名</h3>
</div>
</div>
</div>
card__header-inner-title のように、階層をそのまま名前に反映しようとすると、名前がどんどん長くなり、かえって読みにくくなります。
逆に、分けなさすぎると、次のようになります。
<div class="card">
<div>
<h3>商品名</h3>
<p>1,980円</p>
<button>カートに入れる</button>
</div>
</div>
これでは、CSS 側から個別のスタイルを当てる手がかりがありません。
適切な粒度の目安は、「単独でスタイルを指定する必要があるかどうか」です。タイトル・価格・ボタンはそれぞれ独立してスタイルを変える可能性が高いので Element にする価値がありますが、単に見た目をまとめるだけの入れ子(card__header-inner のような中間の入れ物)は、実際にスタイルの違いが必要になるまでは作らなくてもかまいません。
.card {
display: flex;
flex-direction: column;
gap: 8px;
}
先ほどの例では card__header-inner を用意しなくても、.card 自身に配置の指定を書けば、余計な入れ子を増やさずに済みます。
🔰 初学者の方へ 最初から完璧な粒度を決めようとしなくてかまいません。書き始めてみて、「このタグにも個別のスタイルが必要になった」と気づいたタイミングで Element を追加していく進め方でも十分です。
名前が長くなることをどう受け入れるか
.card__button や .form-field__error-message のように、役割にもとづいた名前は、見た目由来の短い名前よりも長くなりがちです。この長さを「面倒だ」と感じる人も少なくありません。
ですが、名前の長さと保守のしやすさは、多くの場合トレードオフの関係にあります。
/* 短いが、何のクラスか本文を読まないとわからない */
.b1 {
padding: 16px;
}
/* 長いが、名前だけで役割がわかる */
.product-card__title {
padding: 16px;
}
.b1 は入力の手間が少なく済みますが、半年後にこのコードを読み返したとき、.b1 が何を指しているかを思い出すのに時間がかかります。.product-card__title は入力の手間こそ増えますが、名前を読むだけで「商品カードのタイトル」だとわかります。
エディタの入力補完機能を使えば、長いクラス名を毎回すべて手入力する必要はありません。名前の長さによる入力コストは、思っているほど大きな負担にはならないことがほとんどです。それよりも、半年後・1 年後に読み返したときの理解のしやすさのほうが、長期的には価値があります。
📖 もっと詳しく BEM 以外にも、命名の考え方はいくつか存在します。例えば、ハイフンだけで区切る書き方や、コンポーネント単位でファイルごとクラス名の重複を避ける考え方などです。どの記法を選んでも、「役割で名付ける」という土台の発想は共通しています。記法そのものよりも、チーム内で 1 つのルールに統一されていることのほうが重要です。
名前の一貫性がチームの共通言語になる
役割で名付ける発想は、1 人で書いているうちは効果を実感しにくいかもしれません。真価が出るのは、複数人で同じ CSS を触るようになったときです。
<div class="alert alert--error">
<p class="alert__message">入力内容にエラーがあります</p>
</div>
このマークアップを初めて見たメンバーでも、.alert が通知の部品であること、.alert--error がエラー用のバリエーションであること、.alert__message が通知の中の本文であることを、コードを読むだけで推測できます。命名のルールが揃っていれば、書いた本人に質問しなくても、名前だけで意図が伝わります。
逆に、命名のルールが揃っていないチームでは、同じ役割の部品に対して人によって違う名前が付けられ、.alert と .notice と .message-box が同じ意味で混在するといった事態が起こりやすくなります。役割で名付けるというルールは、個人の書き方の癖ではなく、チーム全体で共有する約束事として機能して初めて効果を発揮します。
💡 ポイント 命名規則は「正しさ」よりも「一貫性」が優先される領域です。BEM を採用してもしなくても、チーム内で同じ判断基準を使い続けることが、名前を読むだけで意図が伝わる状態を作ります。
実習:見た目由来の名前を役割の名前に書き直す
次の HTML と CSS には、見た目由来の名前が使われています。これを役割にもとづく名前に書き直してみましょう。
<div class="green-panel">
<h3 class="big-text">今月のキャンペーン</h3>
<p class="small-text">先着100名様限定</p>
<button class="blue-button">詳しく見る</button>
</div>
書き直しの手順は次のとおりです。
.green-panel全体が何の役割を持つ部品かを考え、Block の名前を決める(例:.promo)- 見出しと本文が Block の中で何の役割かを考え、Element の名前を決める(例:
.promo__title、.promo__text) - ボタンも同様に Element として名前を付ける(例:
.promo__button) - 色や文字サイズは Element の CSS 側に記述し、クラス名からは色や大きさの情報を取り除く
- 書き直した後、デザインの色が変わった場合にクラス名の変更が不要になっているかを確認する
まとめ
このレッスンでは、以下のことを学びました。
- 見た目由来の名前は、見た目が変わったときに実態とずれてしまうこと
- クラス名は見た目ではなく役割で名付けるべきであること
- BEM は Block・Element・Modifier という 3 つの単位で名前を組み立てる考え方であること
- クラス名だけで見た目が完結するように書くと、詳細度が均一に保たれること
- 命名の粒度は「単独でスタイルを指定する必要があるか」を目安に決めること
- 名前が長くなることは、長期的な保守のしやすさとのトレードオフであること
次のレッスンでは、CSS の値を一元管理する CSS カスタムプロパティを学びます。同じ色や余白の値を何度も書いていないか、コード全体を見直すきっかけになるはずです。
確認クイズ
このレッスンの理解度をチェックしましょう。