私は数年前、CSS設計(SMACSS や REMM など)について何本か記事を書きました。
当時いちばん悩んでいたのは「命名」です。
命名の衝突を防ぐルール作り、ネームスペースの確保、実装より命名に時間がかかる感覚 — CSS設計の苦労の多くは、ここに集約されていました。
それも過去の話となり、Tailwind CSS、CSS Modules、@scope、Cascade Layers と、スタイリングの選択肢は大きく変わりました。
そして「CSS設計はもう不要なのでは?」と感じることも多くなりました。
結論から言うと、私の答えは 「命名規約は役目を終えた。でも設計は残った」 です。
この記事では、何が不要になり、何が形を変えて残ったのかを整理します。
CSS のスタイリング方針を考えるときの糧にしていただけたら幸いです。
CSS設計は何を解決しようとしていたのか
本題の前に、そもそも CSS設計が何のために生まれたのかを整理します。
CSS には長らく、構造的な弱点がありました。
- すべてのセレクタが全要素に影響するグローバルスコープで気付かぬ衝突が起きる
- 後から上書きするために詳細度を上げる「詳細度の戦争」
!importantが乱発される - 1 つのスタイル変更が、どこに波及するか分からず影響範囲が予測不能
BEM、SMACSS、FLOCSS、REMM…。
これらの CSS設計手法は、この弱点を「命名規約」で乗り越えようとした ものです。
.block__element--modifier のような命名規則で擬似的にスコープを作り、衝突を人間の規律で防ぐのが当時のベストプラクティスでした。
私自身も命名規則に加えて「ネストは 3 つまで」「シングルクラスで書く」といったルールを敷いて、命名の一貫性を保とうとしていました。
裏を返せば、それだけ命名にコストと神経を使っていた ということです。
命名規約は「不要になった」
ここ数年のツールとブラウザの進化で、命名規約が解決していた問題は、仕組みが自動で解決するようになりました。
スコープは、もう命名で作らなくていい
かつては .card__title のような命名で擬似スコープを作っていました。今は本物のスコープが手に入ります。
/* かつて: 命名でスコープを擬似的に表現 */
.card__title { font-size: 1.2rem; }
/* 今: @scope でスコープを区切る(Chrome/Edge 118〜、Safari 17.4〜、Firefox 146〜) */
@scope (.card) {
.title { font-size: 1.2rem; }
}
@scope は 2025 年に全主要ブラウザに出揃い、Baseline 入りしました。
さらに、CSS Modules はビルド時にローカルクラス名を一意な名前へ変換し、Vue(data-v-* 属性の付与)や Svelte(ハッシュ付きクラスの追加)も、コンポーネント単位のスコープを自動で実現してくれます。
いずれにせよ、人間が衝突を避けるための命名を考える必要は、ほぼなくなりました。
詳細度の戦争は、Cascade Layers で終わる
「後から上書きするために詳細度を上げる」という不毛な戦いも、@layer(2022 年から主要ブラウザで baseline)で構造的に解決できます。
@layer base, components, utilities;
@layer base {
a { color: blue; }
}
@layer utilities {
.text-red { color: red; } /* レイヤーが後なら、詳細度に関係なく勝つ */
}
レイヤーをまたぐ通常宣言では、詳細度よりレイヤーの順序が優先されます。
「上書きするためだけに詳細度を盛る」必要が大きく減るので、!important への依存も和らぎます。
ただし「詳細度が完全になくなる」わけではありません。
同じレイヤー内では従来どおり詳細度で決まり、!important を使うとレイヤーの優先順位は逆転します。あくまで「カスケードにレイヤーという整理軸が増えた」と捉えるのが正確です。
ユーティリティファーストなら、そもそも命名しない
Tailwind CSS のようなユーティリティファーストのアプローチでは、そもそもクラスを命名しません。
<!-- 命名する代わりに、既存のユーティリティを組み合わせる -->
<div class="rounded-lg p-4 shadow">...</div>
「命名に時間がかかる」という、CSS設計時代の最大の悩みそのものが消えるわけです。
このような状況からBEM 的な命名規約は、その役目を終えつつある と感じました。
「形を変えて残った」のは設計
では CSS設計は丸ごと不要かというと、そうではないと考えています。
「命名規約」という手段が不要になっただけで、設計が解決しようとしていた目的は残っています。
① デザイントークンの設計
命名しなくなった代わりに、どんな値を許可するかという設計が重要になりました。
Tailwind を使うにしても、「色や余白の選択肢をどう絞るか」を設計しないと、p-[13px] のような場当たり的な値が散らばります。
これはまさに、私が別記事で書いた Tailwind の arbitrary values を 3 層構造で管理する 話そのものです。
ツールが命名から解放してくれた分、「値の体系をどう設計するか」に主戦場が移っただけなのです。
値の設計について詳しくは、こちらの記事も参考にしてみてください。
② コンポーネント分割の粒度
スコープが自動で手に入っても、「どの単位でコンポーネントを切るか」は人間が設計するしかありません。
粒度が大きすぎれば再利用できず、小さすぎれば管理が煩雑になる。
これは命名規約とは無関係に、ずっと残る設計判断です。
③ 影響範囲を制御するという「目的」そのもの
そもそも CSS設計の目的は 「変更の影響範囲を予測可能にする」 ことでした。
@scope や Cascade Layers は、この目的をより良い手段で達成しているだけで、目的自体が消えたわけではないと考えています。
手法を学ぶとき、「BEM の書き方」だけを覚えると、ツールが変わった瞬間に知識が陳腐化します。
でも「なぜスコープを区切りたいのか」「なぜ詳細度を管理したいのか」という目的を理解していれば、手段が変わっても応用が効きます。
まとめ
「不要になったもの」と「残ったもの」
今回の整理を表にまとめます。
| CSS設計が解決していた問題 | かつての手段(命名規約) | 今の手段 | 設計は必要か |
|---|---|---|---|
| スコープの分離 |
.block__element 命名 |
@scope / CSS Modules / scoped |
手段は自動化、判断は残る |
| 詳細度の制御 | 命名規則・シングルクラス |
@layer(Cascade Layers) |
自動化された |
| 命名の衝突回避 | ネームスペース設計 | ビルド時のユニーク化 / ユーティリティ | ほぼ不要に |
| 値の一貫性 | (手薄だった) | デザイントークン設計 | むしろ重要に |
| コンポーネント粒度 | モジュール定義 | コンポーネント設計 | 変わらず必要 |
数年前、私は「命名に時間がかかる」ことに悩み、独自の命名ルールを敷いていました。
今振り返ると、あの苦労の大半は、ツールが解決してくれる領域だったのだと分かります。
でも、それは「設計が不要になった」のではありません。
設計の重心が「命名」から「値とコンポーネントの体系」へ移っただけです。
むしろ、命名という雑務から解放された分、本質的な設計に集中できるようになったとも言えます。
本記事の要点は下記のとおりです。
- CSS設計が解決していたのは「スコープ・詳細度・命名衝突・影響範囲」の問題
-
@scope/@layer/ CSS Modules / ユーティリティが自動で解決し、命名規約は役目を終えつつある - デザイントークン設計、コンポーネント粒度、影響範囲の制御など設計そのものは残る
- 手法(BEM の書き方)ではなく 目的(なぜスコープを区切るか) を理解しておくと、手段が変わっても応用が効く
「CSS設計はもう不要?」への私の答えは、「命名規約はね。でも設計は、形を変えて残っている」 です。
ツールに命名を任せられる今だからこそ、その先の設計に頭を使っていきたいですね。
関連記事
数年前に書いた CSS設計まわりの記事です。「当時いかに命名と格闘していたか」の記録としてどうぞ。