CSSのクラス名の付け方について、ルールが生まれた背景、BEM・SUIT CSS・SMACSS・FLOCSS・Tailwind CSSの書き方と特徴、CSSの新しい機能、このサイトのルール、などについてまとめました。
CSSクラス名の付け方・トレンド
CSSクラス名の付け方には、運用していく中で生まれたいくつかのルールがあります。ルールを設けると、ページ全体で共有された記述の衝突を防げるうえ、判断に迷わずに制作できるようになります。
以下のような背景で、複数のルールが生まれています。
| 困りごと | 生まれた解決策 |
|---|---|
| クラスがページ全体で共有され、名前がぶつかる | BEM・SUIT CSS(名前に親を含めて一意にする) |
| 詳細度(どのスタイルを優先するかを決める点数)の上書き合戦になる | BEM(クラス1つで指定する)・FLOCSS(層の順番を決める) |
| 大人数で書き方がばらばらになる | SMACSS・FLOCSS(ルールの種類と接頭辞を決める) |
| 名前を考えるのが大変で、CSSが増え続ける | Tailwind CSS(名前を付けない) |
| コンポーネント単位で作るようになった | CSS Modules・scoped style(ツールが名前を一意にする) |
最近では、名前の衝突を防ぐ役割は、人が決める命名ルールから、ビルドツール、さらにブラウザの機能へと移ってきています。
CSSをより使いやすく、管理しやすくするための手段が広がっています。
BEM(命名規則)
BEMは、Block・Element・Modifierの3要素でクラス名を書く命名規則です。
| 項目 | 内容 |
|---|---|
| クラス名の例 | .menu__item・.menu_hidden |
| 要素 | Blockと__でつなぐ |
| Modifier(状態や種類) | _でつなぐ。--でつなぐ「Two Dashes style」も公式に紹介されている |
<header class="header">
<a class="header__logo" href="/"><img src="/logo.svg" alt="サイト名"></a>
<button class="header__menu-btn header__menu-btn--open" aria-expanded="true" aria-controls="menu">メニュー</button>
<nav class="header__nav" id="menu">…</nav>
</header>
- Blockに
__で要素をつなぐので、どの部品の一部かがクラス名だけでわかる - クラス1つで指定するので、詳細度が上がりにくい
- 名前が長くなる
- 要素とModifierのどちらにするか迷いやすい
SUIT CSS(命名規則)
SUIT CSSは、コンポーネントを単位にクラス名を付ける命名規則です。
| 項目 | 内容 |
|---|---|
| クラス名の例 | .Tweet-header・.Button--default・.is-expanded |
| コンポーネント名 | PascalCaseで書く |
| 子要素 | -でつなぎ、camelCaseで書く |
| Modifierと状態 | Modifierは--、状態はis-で書く |
<header class="Header">
<a class="Header-logo" href="/"><img src="/logo.svg" alt="サイト名"></a>
<button class="Header-menuBtn is-open" aria-expanded="true" aria-controls="menu">メニュー</button>
<nav class="Header-nav" id="menu">…</nav>
</header>
- コンポーネント名だけを大文字で始めるので、どこからが1つの部品かが見分けやすい
- 状態を
is-で分けられる - 大文字と小文字が混ざるので、書き間違いが起きやすい
SMACSS(命名規則+設計手法)
SMACSSは、CSSのルールを5種類に分けて書く設計手法です。
| 項目 | 内容 |
|---|---|
| ルールの種類 | Base・Layout・Module・State・Theme |
| レイアウト | l-で始める |
| モジュールの子要素 | モジュール名を頭に付けて、ハイフンでつなぐ |
| 状態 | is-hiddenのようにis-で表す |
<header class="l-header">
<a class="logo" href="/"><img src="/logo.svg" alt="サイト名"></a>
<button class="menu-btn is-open" aria-expanded="true" aria-controls="menu">メニュー</button>
<nav class="menu" id="menu"><a class="menu-item" href="/">…</a></nav>
</header>
- ルールの種類ごとに書き方が変わる(ヘッダーの枠はLayoutの
l-、メニューはModuleのmenu、その子要素はmenu-item) - ルールの種類ごとに、書く場所が決まる
- 状態の
is-はほかの方式でも使われていて、覚えたことを流用しやすい - 要素の名前の付け方は厳密に決まっていないので、細かい書き方はサイトごとに決める必要がある
FLOCSS(命名規則+設計手法)
FLOCSS(フロックス)は、CSSを3つの層に分けて書く設計手法で、日本語で公開されています。
| 項目 | 内容 |
|---|---|
| 層 | Foundation・Layout・Object |
| Objectの分け方 | Component(c-)・Project(p-)・Utility(u-) |
| 要素とModifier | BEMの変形(MindBEMding)で__と--を使う |
| 参考にした手法 | OOCSS・SMACSS・BEM・SUIT CSSなど |
<header class="l-header">
<a class="p-header__logo" href="/"><img src="/logo.svg" alt="サイト名"></a>
<button class="c-menu-btn is-open" aria-expanded="true" aria-controls="menu">メニュー</button>
<nav class="p-header__nav" id="menu">…</nav>
</header>
- 接頭辞で層を表す(ヘッダーの枠はLayoutの
l-、使い回すボタンはComponentのc-、サイト固有の部品はProjectのp-) - 層と接頭辞で、どこに書くかが決まる
- 大人数でも書き方がそろう
- ルールが多く、小さなサイトでは手間が増える
c-とp-のどちらにするか迷いやすい
Tailwind CSS(CSSフレームワーク)
Tailwind CSSは、1つの役割だけを持つクラスを並べて書く、ユーティリティファーストのCSSフレームワークです。
| 項目 | 内容 |
|---|---|
| クラス名の例 | flex・px-6・md:hidden |
| 部品の名前 | 付けない |
<header class="flex items-center justify-between px-6 py-4">
<a href="/"><img class="h-8 w-auto" src="/logo.svg" alt="サイト名"></a>
<button class="p-2 md:hidden aria-expanded:bg-gray-100" aria-expanded="true" aria-controls="menu">メニュー</button>
<nav class="hidden md:flex gap-6" id="menu">…</nav>
</header>
- 見た目を表すクラスを並べるので、部品の名前を考えなくてよい
- 開いたときの見た目は、
aria-expanded:のようなバリアントで切り替えられる - CSSファイルが増え続けない
- HTMLのクラスが長くなる
- Tailwind独自のクラス名を覚える必要がある
Tailwind CSSの導入や使い方は、Tailwind CSSの記事で詳しく確認しています。
CSS Modules・Astroのscoped style(仕組み)
CSS ModulesとAstroのscoped styleは、クラス名をビルド時に一意にして、名前の衝突を防ぐ仕組みです。
| 項目 | 内容 |
|---|---|
| CSS Modules | CSSファイルの中のクラス名が、標準でそのファイルの中だけに閉じる |
| Astroのscoped style | コンポーネントの<style>に書いたスタイルが、ビルド時にそのコンポーネントだけに当たるよう変換される |
<header>
<a class="logo" href="/"><img src="/logo.svg" alt="サイト名"></a>
<button class="menu-btn" aria-expanded="true" aria-controls="menu">メニュー</button>
<nav id="menu">…</nav>
</header>
<style>
.logo { display: block; }
.menu-btn { padding: 8px; }
</style>
- Astroではビルド後に
.logo[data-astro-cid-xxxx]のような形に変換されるので、logoのような短い名前でもほかのコンポーネントとぶつからない - フレームワークやビルドツールに依存する
- コンポーネントをまたぐスタイルは、別の方法が必要になる
CSSの新しい機能 @layer・@scope
CSSそのものにも、クラス名に頼らずに、スタイルの優先順位や当たる範囲を管理できる機能が増えています。
@layer(カスケードレイヤー)
スタイルのグループごとに優先順位を宣言できる。MDNのBaselineでは、2022年3月から主要なブラウザで使える@scope
スタイルが当たる範囲を、DOMの一部に限定できる。MDNのBaselineでは、2026年3月から最新の主要なブラウザで使える(古いブラウザでは動かない場合がある)
@scopeを使うと、BEMのように親の名前をクラス名に含めなくても、スタイルが当たる範囲を絞れます。ただし使えるようになったばかりなので、古いブラウザへの対応が必要なサイトでは、命名ルールと組み合わせるのが現実的です。
このサイトのクラス名の付け方ルール
このサイト(まなびのすけ)では、この記事で紹介した方式をそのまま使うのではなく、独自ルールを定めて、サイトガイドラインに載せています。書き方はSUIT CSSに近い形です。大文字は使いません。
- 子要素は「親クラス名-役割」でつなぐ(
.hd-menu→.hd-menu-btn)。 - バリエーションは
--でつなぐ(.tagbtn--cat) - JavaScriptで付け外しする状態は
is-・has-で始める(.is-hidden・.has-peek) - ツール固有のクラスは、ツール名を頭に付ける(
.contrast-ratio) - 略語は決めたものだけ使う(
hd=ヘッダー、ic=アイコン、mb=まなびのすけ など)
実際のヘッダーは、次のような組み方です。
<a class="brand" href="/">まなびのすけ</a>
<button class="hd-menu-btn" type="button" popovertarget="site-menu" aria-controls="site-menu" aria-expanded="false">メニュー</button>
<div id="site-menu" class="hd-menu" popover>…</div>
フレームワークはAstroを使っていて、コンポーネントの中だけで使うクラスはscoped styleに書いています。
AIエージェントにコードを書かせるときは、まずサイトガイドラインを読ませて、新しいクラスも同じ書き方にそろえています。AIエージェントへのルールの渡し方は、AIエージェントの記事で確認しています。
ルールを決めておけば、AIにも指示しやすく、また人間が書くときも読むときも楽になりますね。
よくある質問(FAQ)
Q. PascalCaseとcamelCaseの違いは何ですか?
1文字目が大文字か小文字かの違いです。PascalCaseはNoteCardのように各単語の先頭を大文字にし、camelCaseはnoteCardのように2語目から先頭を大文字にします。JavaScriptでは、クラスやコンポーネントにPascalCase、変数や関数にcamelCaseを使うのが一般的です。CSSのクラス名には、menu-btnのようなケバブケース(ハイフン区切り)がよく使われます。
Q. BEMとFLOCSSはどちらを選べばいいですか?
クラス名の書き方だけをそろえたいならBEM、CSSファイルの分け方まで決めたいならFLOCSSが向いています。FLOCSSは要素とModifierの書き方にBEMの変形を使っているため、BEMを覚えておけばFLOCSSにも移りやすいです。
Q. Tailwind CSSを使えばクラス名のルールは要りませんか?
部品ごとの名前を考える必要はほぼなくなりますが、ルールが不要になるわけではありません。どこまでユーティリティで書き、どこからコンポーネントに切り出すかや、@themeに書くテーマ変数の名前のそろえ方は決めておく必要があります。