CSSネストとは、Sassなどのツールを使わずにCSSだけでセレクタを入れ子に書ける標準機能です。2023年以降に主要ブラウザへ実装され、現在はビルド環境なしで利用できます。
この記事では、CSSネストの基本ルールから、BEM命名・FLOCSS構成と組み合わせた実践的な書き方までを初心者向けに解説します。コード例はコピーしてそのまま動作するものだけを掲載しています。
最初に、もっとも間違えやすい点を1つだけ先に共有します。Sassでよく使う &__title のような文字の連結は、ネイティブのCSSネストでは使えません。ここを知らないまま書くと、スタイルがまったく効かない状態でつまずきます。詳しくは本文で解説します。
CSSネストとは? 何が便利になるのか
CSSネストは、親セレクタの中に子セレクタを入れ子で書ける機能です。まずは、従来の書き方と比べてみます。
/* 従来の書き方:セレクタを毎回フルで書く */
.container {
background: #f4f4f4;
padding: 20px;
}
.container .box {
border: 1px solid #ccc;
padding: 10px;
}
.container .box p {
color: #333;
font-size: 16px;
}/* CSSネスト:親の中に入れ子で書ける */
.container {
background: #f4f4f4;
padding: 20px;
.box {
border: 1px solid #ccc;
padding: 10px;
p {
color: #333;
font-size: 16px;
}
}
}どちらも結果は同じですが、ネストを使うと次の利点があります。
- 親子関係が見た目で分かるため、HTMLの構造と対応づけて読める
- 同じセレクタを何度も書かずに済み、打ち間違いが減る
- 1つの部品に関するスタイルが1か所にまとまり、削除や移動がしやすい
これまでは同じことをするのにSass(SCSS)やLessが必要でしたが、現在はブラウザがそのまま解釈してくれます。コンパイル(変換)作業が不要になったのが最大の変化です。
覚えるルールは3つだけ
CSSネストで迷うのは、記号の &(アンパサンド)を付けるかどうかだけです。次の3つを押さえれば実務で困りません。
ルール1:中の要素を指すだけなら & は不要
「親の中にある○○」を指す場合は、そのまま書けます。
.card {
padding: 1rem;
/* .card の中の .title に当たる(= .card .title) */
.title {
font-size: 1.2rem;
}
/* タグ名でも書ける(= .card p) */
p {
color: #666;
}
}なお、実装当初は & が必須でした。現在は不要になっていますが、古い解説記事では & .title と書かれている場合があります。どちらの書き方でも動作します。
ルール2:くっつけたいときは & を先頭に置く
「その要素自体がホバーされたとき」「その要素自体に別のクラスが付いたとき」のように、間にスペースを入れずに条件を足したい場合は & が必要です。
.button {
background-color: #0078ff;
color: #fff;
/* = .button:hover */
&:hover {
background-color: #005ecb;
}
/* = .button.is-active(2つのクラスが同時に付いた状態) */
&.is-active {
background-color: #005ecb;
}
/* = .button::after */
&::after {
content: " →";
}
}ここで & を書き忘れて .is-active とだけ書くと、.button .is-active(ボタンの中にある要素)という別の意味になります。効かないときは、まずここを疑ってください。
ルール3:& で文字をつなぐことはできない
ここが本記事でもっとも重要な注意点です。Sassでは書けた &__title のような連結は、ネイティブCSSネストでは使えません。
.card {
padding: 1rem;
/* NG:ネイティブCSSでは無効。このルールごと無視される */
&__title {
font-size: 1.2rem;
}
}Sassの & は「親のクラス名という文字列」として扱われるため連結できますが、CSSの & は「親セレクタそのものを指す記号」であり、文字列ではありません。MDNでも「CSSネストでは連結はできない」と明記されています(出典:MDN — Using CSS nesting)。
やっかいなのは、エラーが表示されずにそのルールだけが静かに無視される点です。「書いたのに反映されない」と感じたときは、この形になっていないか確認してください。正しい書き方は後半の「BEM × CSSネストの正しい書き方」で解説します。
CSSネストとSass/Lessの違い
| 比較項目 | ネイティブCSSネスト | Sass / Less |
|---|---|---|
| 使用環境 | ブラウザでそのまま動く | コンパイラ(変換ツール)が必要 |
| ビルド作業 | 不要 | 必要 |
&__elem の連結 | できない | できる |
| 変数・関数・Mixin | なし(CSS変数は利用可) | あり |
| 学習コスト | 低い(CSSの延長) | やや高い(独自構文を覚える) |
CSSネストはSassほど多機能ではありませんが、入れ子構造だけが目的ならこれで十分です。ビルド環境を用意せずに始められるのが最大の利点で、小規模サイトやWordPressテーマの部分修正と相性が良い機能です。
ブラウザ対応状況
CSSネストは2023年から順次実装され、& なしで書ける現在の仕様には次のバージョンから対応しています。
| ブラウザ | 現行仕様に対応 | 備考 |
|---|---|---|
| Google Chrome | 120以降 | 112〜119は & 必須の旧仕様 |
| Microsoft Edge | 120以降 | 112〜119は & 必須の旧仕様 |
| Firefox | 117以降 | 当初から現行仕様 |
| Safari | 17.2以降 | 16.5〜17.1は & 必須の旧仕様 |
対応状況の出典はCan I use(CSS Nesting)です。旧仕様のブラウザも一定数残っているため、不安な場合は常に & を付けて書くのが安全策になります。& は付けても動作が変わらないため、チームのルールとして「常に付ける」と決めてしまうのも有効です。
BEM × CSSネストの正しい書き方
BEMは block__element--modifier の形でクラス名を付ける命名規則です。前述のとおりネイティブCSSでは &__title と書けないため、組み合わせ方には工夫が必要です。取れる選択肢は次の2つです。
方法1:Elementはフラットに書く(推奨)
BEMのElement(card__title など)はトップレベルに並べ、ネストは状態や画面幅などの条件だけに使う方法です。
.card {
display: flex;
padding: 1rem;
background: #fff;
/* 条件つきの指定だけをネストする */
&:hover {
background: #f7f7f7;
}
&.is-selected {
outline: 2px solid #0070f3;
}
@media (width > 768px) {
flex-direction: row;
}
}
/* Element と Modifier はフラットに書く */
.card__title {
font-size: 1.2rem;
font-weight: bold;
}
.card__description {
font-size: 1rem;
color: #666;
}
.card--large {
padding: 2rem;
}一見すると入れ子が減って損をしたように見えますが、実はこれがBEM本来の形です。BEMのクラス名はそれだけで場所が特定できるように作られているため、入れ子にしなくても構造は失われません。むしろセレクタが短いままなので、あとから上書きしやすいという利点があります。
方法2:どうしても入れ子で書きたいならSassを使う
&__title のような書き方を続けたい場合は、Sass(SCSS)やPostCSSのプラグインを使います。これらは書いたコードを通常のCSSに変換してから配信するため、連結が可能です。
/* これはSass(SCSS)のコード。ブラウザには変換後のCSSが届く */
.card {
padding: 1rem;
&__title {
font-size: 1.2rem;
}
&--large {
padding: 2rem;
}
}ただしビルド環境が必要になるため、「ビルド不要」というCSSネストの利点は失われます。新規に始めるなら方法1、既存のSassプロジェクトを続けるなら方法2と考えるのが分かりやすい基準です。
ネストで詳細度が上がる点に注意
ネストで書いたセレクタは、展開すると .card .title のような形になります。これは .title 単体よりも詳細度(=どのスタイルが優先されるかの強さ)が高くなるため、あとから .title だけで上書きしようとしても効きません。
BEMのようにクラス名で場所を表す設計なら、そもそも深いネストが不要になります。ネストは「便利だから使う」のではなく、「条件を書くときだけ使う」と決めておくと事故が減ります。
FLOCSS形式のディレクトリ構成と組み合わせる
FLOCSSは、CSSファイルをFoundation・Layout・Objectの3層に分けて管理する設計手法です。CSSネストと組み合わせると、1ファイル=1部品の形で自己完結させやすくなります。
| ディレクトリ | 役割 | 入れるもの |
|---|---|---|
foundation/ | 土台 | リセットCSS、CSS変数、基本のタグスタイル |
layout/ | 大枠 | header、footer、sidebar など |
object/component/ | 汎用パーツ | button、label など最小単位の部品 |
object/project/ | サイト固有 | 記事カード、問い合わせフォームなど |
object/utility/ | 微調整 | u-mb16、u-text-center など |
読み込む順番は上から下(foundation → layout → object)です。あとから読み込まれたCSSが優先されるため、土台から細かい調整へと段階的に上書きしていく形になります。
なおfoundation層には、ブラウザ間の初期スタイルの差を吸収するリセットCSSを配置します。土台を揃えておくことで、object層以降のスタイル崩れを防げます。
メディアクエリもネストできる
CSSネストの利点がもっとも分かりやすいのがメディアクエリです。従来はセレクタを再度書く必要がありましたが、ネストなら部品の中に書けます。
.container {
padding: 1rem;
@media (width > 1024px) {
padding: 2rem;
}
}ファイル末尾にメディアクエリをまとめて書く方式だと、「この部品のレスポンシブ指定はどこにあるのか」を探す手間が発生します。ネストならその部品を消すだけで関連指定もまとめて消せるため、消し忘れによる不要なCSSの蓄積を防げます。
読みやすさを保つ書き方のルール
プロパティの記述順を揃える
プロパティを書く順番をチームで固定しておくと、差分レビューが楽になります。次の並びが一般的です。
- 表示・配置系:
display、position、z-index - ボックス系:
width、height、margin、padding - 背景・枠線系:
background、border、box-shadow - 文字系:
font、color、text-align - 動き系:
transition、animation、transform
.button {
display: inline-flex;
justify-content: center;
width: 160px;
height: 48px;
background: #0070f3;
border: none;
color: #fff;
font-size: 16px;
transition: background 0.3s;
&:hover {
background: #005bd1;
}
}ユーティリティクラスは u- を付ける
余白や文字寄せなどの微調整用クラスには u- を付けて、部品用のクラスと区別します。役割が名前から分かるため、削除してよいか判断しやすくなります。
.u-mb16 {
margin-bottom: 16px;
}
.u-text-center {
text-align: center;
}セクションの区切りをコメントで示す
/* ----------------------------------------
Component: Button
---------------------------------------- */ファイル単位・部品単位で区切りを入れておくと、目的の場所を探す時間が短くなります。
やってはいけない書き方
| 避けるべき書き方 | 何が起きるか |
|---|---|
&__elem で連結する | ネイティブCSSでは無効。エラーも出ずに無視される |
| 3階層以上の深いネスト | 詳細度が上がり、あとから上書きできなくなる |
!important の多用 | 上書きの連鎖が起き、修正できないCSSになる |
| タグ名やIDを起点にしたネスト | HTML構造の変更で壊れ、部品を使い回せなくなる |
ネストは深く書けてしまうぶん、意識しないと詳細度が上がり続けます。目安は2階層、最大でも3階層までと決めておきましょう。それ以上必要になったときは、別の部品として切り出すサインです。
ネストが効かないときの確認手順
ネストは書き間違えてもエラーが出ないため、原因を切り分ける手順を知っておくと解決が早くなります。上から順に確認してください。
- 連結になっていないか:
&__title、&--largeの形はネイティブCSSでは無効です。もっとも多い原因がこれです。 &の付け忘れ・付けすぎ:.is-activeと書くと「中にある要素」、&.is-activeと書くと「自分自身にクラスが付いた状態」です。意味が変わります。- 詳細度で負けていないか:ネストで書いた指定は展開すると長いセレクタになるため、別の場所の短い指定では上書きできません。
確実なのは、ブラウザの検証ツール(デベロッパーツール)で確認する方法です。要素を選択して「Styles」パネルを見ると、ネストが展開された後の実際のセレクタが表示されます。.card .card__title のように意図しない形になっていれば、書き方が原因だと特定できます。
また、そもそもルールとして認識されていない場合は、Stylesパネルにその指定自体が現れません。「打ち消し線で表示される=詳細度負け」「そもそも表示されない=構文が無効」と覚えておくと、原因を素早く切り分けられます。
よくある質問(FAQ)
Q. CSSネストとは何ですか?
CSSの標準機能として追加されたネスト記法で、SassやLessを使わずにセレクタの入れ子構造を書けます。.card { .title { … } } のように記述でき、コードの可読性と保守性が向上します。主要ブラウザはすべて対応済みです。
Q. Sassでよく使う &__title はCSSネストでも書けますか?
書けません。ネイティブCSSの & は親セレクタを指す記号であり、文字列の連結には使えないためです。エラーは表示されずそのルールだけが無視されるため、BEMのElementはネストせずフラットに書くか、Sassなどのビルドツールを使ってください。
Q. & はどんなときに必要ですか?
:hover などの疑似クラス、::after などの疑似要素、.is-active のようにクラスを重ねる場合に必要です。逆に「親の中にある要素」を指すだけなら省略できます。判断に迷う場合は常に付けておけば動作は変わりません。
Q. どこまで深くネストして良いですか?
目安は2階層、最大でも3階層までです。深くするほど詳細度が上がり、あとから別の場所で上書きできなくなります。深くなってきた場合は、その部分を独立した部品として切り出すのが正しい対処です。
Q. BEMとネストは相性が悪いのでしょうか?
連結ができない点だけ注意すれば相性は良好です。BEMのElementはフラットに書き、疑似クラス・状態クラス・メディアクエリだけをネストする形にすると、構造が読みやすく詳細度も上がりません。
Q. SassやPostCSSはもう不要になりますか?
入れ子構造だけが目的なら不要です。ただし変数の演算やMixin、ファイル結合などSass固有の機能が必要な場合や、BEMの連結記法を使い続けたい場合は引き続き有効です。プロジェクトの要件で選び分けてください。
まとめ
| 項目 | 押さえるポイント |
|---|---|
| CSSネスト | ビルド不要で入れ子が書ける標準機能 |
& の役割 | 親セレクタを指す記号。文字の連結には使えない |
| BEMとの組み合わせ | Elementはフラット、条件だけネストする |
| FLOCSS構成 | foundation → layout → object の順に読み込む |
| ブラウザ対応 | Chrome / Edge 120以降、Firefox 117以降、Safari 17.2以降 |
CSSネストは、覚えることが少ないわりに効果の大きい機能です。まずは疑似クラスとメディアクエリのネストから使い始め、慣れてきたらBEMやFLOCSSと組み合わせて全体構成を整えていくとよいでしょう。
CSS設計そのものを基礎から知りたい方は、CSS設計の基本|BEM・OOCSS・SMACSS・FLOCSSの違いもあわせてご覧ください。
