CSSネストの7つの書き方をマスター!Sassとの違いもサクッと解説
CSSネストは、2023年4月にChromeがサポートしてから、主要なブラウザでもあっという間に対応が進みました。以前は面倒だったスタイルの記述も、今ではもっと簡単に書けるようになり、コードの読みやすさや管理のしやすさが向上しています。
この記事では、CSSネストの概要や、そのメリット・デメリット、7つの具体的な書き方、そしてSassとの違いについて紹介します。初心者の方でも理解しやすいよう、わかりやすい解説を心がけて進めていきます!
Sassの基本や導入方法について知りたい方は、こちらの記事もぜひチェックしてみてください。
CSSネストとは
「CSSネスト」とは、セレクタやプロパティを階層的に入れ子にする(ネストする)CSSの記述方法のことです。
これまでのCSSは、セレクタをフラットに並べる必要がありました。下記のような感じです。
.navbar {
background-color: #333;
padding: 10px;
}
.navbar ul {
list-style: none;
margin: 0;
padding: 0;
}
.navbar ul li {
display: inline-block;
margin-right: 10px;
}
.navbar ul li a {
color: white;
text-decoration: none;
padding: 5px 10px;
display: block;
}
.navbar ul li a:hover {
background-color: #555;
}
これはこれで、ルールが単純で誰でも理解しやすいのですが、プロジェクトの規模が大きくなるほど、
- 同じセレクタが連続して何度も登場する ⇒ 読みにくい
- 離れた行で同じセレクタを使用してしまう ⇒ 競合が発生
- 関連するスタイルを一括りにできない ⇒ 修正が大変
といった問題を抱えやすくなります。
ウェブ制作の現場では、外部チームが作成したCSSを触ることがよくあります。CSSが複雑で整理されておらず、現状把握だけで時間がかかることも…。
それでは次に、CSSネストを使用してみましょう。CSSネストで先ほどと同じスタイルを実現する場合、以下のようになります。
.navbar {
background-color: #333;
padding: 10px;
ul {
list-style: none;
margin: 0;
padding: 0;
li {
display: inline-block;
margin-right: 10px;
a {
color: white;
text-decoration: none;
padding: 5px 10px;
display: block;
&:hover {
background-color: #555;
}
}
}
}
}
このときのHTMLは下記のような感じ。シンプルなナビゲーションバーをイメージしています。
<div class="navbar">
<ul>
<li><a href="#">ホーム</a></li>
<li><a href="#">プロフィール</a></li>
<li><a href="#">お問い合わせ</a></li>
</ul>
</div>
HTMLと並べてみると、CSSネストはHTMLとの親和性が高いことがよくわかります。どの部分がどのスタイルに対応しているかが直感的に理解しやすくなります。
CSSネストのメリット
CSSネストには、以下のようなメリットがあります。
メリット1:コードが読みやすい
HTMLの親子関係に対応する形でスタイルを入れ子にできるので、スタイルの適用箇所が直感的にわかりやすくなります。
<div class="navbar">
<ul>
<li><a href="#">
.navbar {
ul {
li {
a {
HTMLとCSSの対応関係が明確!
メリット2:修正がラク
関連するスタイルをまとめて記述できるので、コードの整理がしやすく、後からの検索や修正、スタイルの追加が簡単です。
例えば、navbar
クラスをnavigation-bar
に変更したい場合、ネストされたCSS内で親セレクタ(この場合、navbar
)を一箇所だけ修正すれば、その配下にあるすべてのスタイルに自動的に反映されます。
.navbar { /* ←ここだけ変えればOK! */
background-color: #333;
padding: 10px;
ul {
list-style: none;
margin: 0;
padding: 0;
従来のCSSでは、何箇所も修正しないといけないし、セレクタやクラス名がファイル内のあちこちに散らばってしまうことも…。
メリット3:無駄な記述を減らせる
関連するセレクタをネストして記述することで、重複するセレクタの記述を減らし、CSSコードをシンプルに保つことができます。先ほどの例から、セレクタ部分だけを見てみましょう。
.navbar {
}
.navbar ul {
}
.navbar ul li {
}
.navbar ul li a {
}
.navbar ul li a:hover {
}
従来のCSSコードでは、同じセレクタを何度も記述する必要があります。しかし、ネストを使うと以下のように書き換えることができます。
.navbar {
ul {
li {
a {
&:hover {
}
}
}
}
}
同じセレクタを何度も記述する必要がなくなり、コードがすっきり!
CSSネストのデメリット
CSSネストには便利な面がある一方で、使い方を誤るとデメリットに直面することもあります。ここでは、その主なデメリットをいくつか紹介します。
デメリット1:過度なネストに注意
CSSネストを使うことで関連するスタイルをグループ化し、コードを整理しやすくなります。しかし、ネストを深くしすぎると、どの要素に対してスタイルが適用されているのかがわかりにくくなり、コードが複雑化してしまいます。
例えば、以下のようなコードはネストが過度に深く、どの要素にどのスタイルが適用されているのかが一目でわかりにくくなっています。
.navbar {
.navbar-nav {
.nav-item {
.nav-link {
div {
.nav-icon {
div {
.icon-container {
.icon {
.icon-image {
display: block;
width: 100%;
height: auto;
}
}
}
}
}
}
}
}
}
}
適度なネストの深さを保ちましょう!
デメリット2:一貫性が失われやすい
CSSネストは比較的新しい技術なので、開発者ごとに理解度や使い方にばらつきがあります。そのため、チーム内外で異なるアプローチが採用され、一貫性が失われるリスクがあります。
以下のコード例は、同じスタイルシート内で、開発者AがCSSネストを使用し、開発者Bが従来のフラットなCSSを使用しているケースです。
/* 開発者AがCSSネストを使用 */
.navbar {
background-color: #333;
.nav-link {
color: white;
&:hover {
color: #ddd;
}
.icon {
margin-right: 5px;
.icon-background {
border-radius: 50%;
}
}
}
}
/* 開発者Bが従来のフラットなCSSを使用 */
.navbar {
border-bottom: 2px solid #444;
}
.nav-link {
font-weight: bold;
}
.icon-background {
padding: 2px;
}
このように、一貫性の欠如は、スタイルの競合を引き起こし、開発効率を低下させる原因となります。
既存プロジェクトでは、既存のコードスタイルやルールに合わせましょう!
デメリット3:ブラウザ対応が不十分
CSSネストは比較的新しい機能なので、すべてのブラウザで完全にサポートされているわけではありません。特に、古いブラウザではCSSネストが正常に動作しないことがあります。
サイトに実装する際は、対象とするブラウザでの動作を確認しましょう。
ちなみに、私が所有している端末とブラウザでCSSネストをテストした結果は次の通りです。
検証結果(2024年9月現在)
デバイス | ブラウザ | 動作状況 |
---|---|---|
PC | Chrome(バージョン128) | 正常に動作した |
Firefox(バージョン129) | 正常に動作した | |
Safari(バージョン17.6) | 正常に動作した | |
スマホ | iPhone 15(iOS 17.6、Safari) | 正常に動作した |
タブレット | iPad(第5世代、iPadOS 16.7、Safari) | 一部のネスト構造が正しく適用されない問題が発生した※ |
※私のiPad(第5世代)はかなり古く、サポート対象外になっているので正しく動作しませんでしたが、比較的新しいiPadOSのバージョン(iPadOS 17.2以降)では正常に動作すると思われます。
このように、最新のブラウザでは基本的に問題なく動作しますが、古いバージョンでは動作が不安定な場合があります。最新のブラウザ対応状況については、Can I Useでも確認することができます。
ウェブ技術やHTML、CSS、JavaScriptなどのブラウザ対応状況を確認できるオンラインサービスです。開発者が特定の機能がどのブラウザでサポートされているかを調べる際に非常に便利です。
CSSネストの書き方
CSSネストにはさまざまな書き方があります。以下に、従来のCSSとの比較を交えながら、いくつかのネストのパターンを紹介します。
書き方1:基本的な親子関係
まずは、もっとも基本的な親子関係のネストです。従来のCSSでは、各要素を個別に記述する必要がありますが、CSSネストを使うことで関連するスタイルをまとめることができます。
section {
padding: 20px;
h2 {
font-size: 24px;
}
.paragraph {
line-height: 1.6;
}
}
ブラウザは次のように解釈します。
section {
padding: 20px;
}
section h2 {
font-size: 24px;
}
section .paragraph {
line-height: 1.6;
}
書き方2:擬似クラス・疑似要素
擬似クラス(:hover
や:focus
など)や擬似要素(::before
や::after
など)も、「&
」を使って親セレクタと関連付けて記述することができます。
button {
background-color: #007bff;
color: white;
&:hover {
background-color: #0056b3;
}
}
p {
&::before {
content: "注意:";
font-weight: bold;
}
}
ブラウザは次のように解釈します。
button {
background-color: #007bff;
color: white;
}
button:hover {
background-color: #0056b3;
}
p::before {
content: "注意:";
font-weight: bold;
}
CSSネストで使われる「&
(アンパサンド)」は、親セレクタを参照するために使う記号で、ネストしたセレクタの中に記述することで、そのセレクタ自身を呼び出します。
書き方3:結合子
結合子(「>
」「+
」「~
」)は、特定の親子関係や兄弟要素間のスタイルを指定するために使用します。CSSネストでもこれらの結合子を使って、複数の要素間の関係を表現できます。
section {
> p {
margin-bottom: 20px;
}
}
h1 {
+ p {
font-size: 18px;
}
~ p {
color: gray;
}
}
ブラウザは次のように解釈します。
section > p {
margin-bottom: 20px;
}
h1 + p {
font-size: 18px;
}
h1 ~ p {
color: gray;
}
この例では、子セレクタ(>
)、隣接兄弟セレクタ(+
)、および一般兄弟セレクタ(~
)をCSSネスト内で使用しています。
書き方4:複数のクラスと属性セレクタ
複数のクラスや属性を使ったスタイル指定を、CSSネストでまとめて記述できます。
.button {
&.primary {
background-color: #007bff;
color: white;
}
&.secondary {
background-color: #6c757d;
color: white;
}
&[disabled] {
background-color: #e0e0e0;
color: #6c757d;
}
}
ブラウザは次のように解釈します。
.button.primary {
background-color: #007bff;
color: white;
}
.button.secondary {
background-color: #6c757d;
color: white;
}
.button[disabled] {
background-color: #e0e0e0;
color: #6c757d;
}
書き方5:複数の子セレクタ
複数の子セレクタを一括でネストすることで、同じスタイルを複数の要素に適用することができます。
article {
h1,
h2,
h3 {
color: #333;
margin-bottom: 10px;
}
}
ブラウザは次のように解釈します。
article h1,
article h2,
article h3 {
color: #333;
margin-bottom: 10px;
}
書き方6:メディアクエリ
メディアクエリも関連するスタイルと一緒にネストすることができます。
.card {
padding: 20px;
background-color: #f8f9fa;
@media (max-width: 768px) {
padding: 10px;
}
}
ブラウザは次のように解釈します。
.card {
padding: 20px;
background-color: #f8f9fa;
}
@media (max-width: 768px) {
.card {
padding: 10px;
}
}
書き方7:「&」の後置
ここまでは、「&
」をセレクタの前に置く形で使用してきましたが、この記号を内側のセレクタの後に置くことも可能です。
.foo {
color: red;
.bar & {
color: blue;
}
}
ブラウザは次のように解釈します。
.foo {
color: red;
}
.bar .foo {
color: blue;
}
これまでの書き方とは少し違って見えるかもしれませんが、「&
」が「親セレクタ(この場合、foo
)を参照する」ことを理解すれば納得できるかと思います。
「&」の後置について、より実用的な使い方を紹介します!
「&
」の後置は、条件に応じてスタイルを変えたい場面で役立ちます。たとえば、html
要素やbody
要素に、そのページの属性を示すクラス名が振られている場合に、この方法を活用できます。
具体的には、body
要素にサイトのカテゴリを示すクラスが付与されており、そのクラスに基づいてグローバルナビゲーションのカレント状態(現在選択されている状態)を指定する例を紹介します。
<body class="category-profile">
<!-- 中略 -->
<div class="navbar">
<ul>
<li><a href="#">ホーム</a></li>
<li><a href="#">プロフィール</a></li>
<li><a href="#">お問い合わせ</a></li>
</ul>
</div>
<!-- 中略 -->
</body>
この例では、body
要素に「category-profile」というクラスが付与されています。このクラスに基づいて、「プロフィール」のリンクをカレント状態にするために、CSSネストを利用します。
.navbar {
background-color: #333;
padding: 10px;
ul {
list-style: none;
margin: 0;
padding: 0;
li {
display: inline-block;
margin-right: 10px;
a {
color: white;
text-decoration: none;
padding: 5px 10px;
display: block;
&:hover {
background-color: #555;
}
}
body.category-home &:nth-child(1),
body.category-profile &:nth-child(2),
body.category-contact &:nth-child(3) {
a {
font-weight: bold;
background-color: #555;
}
}
}
}
}
ブラウザは次のように解釈します。
.navbar {
background-color: #333;
padding: 10px;
}
.navbar ul {
list-style: none;
margin: 0;
padding: 0;
}
.navbar ul li {
display: inline-block;
margin-right: 10px;
}
.navbar ul li a {
color: white;
text-decoration: none;
padding: 5px 10px;
display: block;
}
.navbar ul li a:hover {
background-color: #555;
}
body.category-home .navbar ul li:nth-child(1) a,
body.category-profile .navbar ul li:nth-child(2) a,
body.category-contact .navbar ul li:nth-child(3) a {
font-weight: bold;
background-color: #555;
}
この書き方では、body
要素に「category-profile」や「category-contact」といったクラスが付与されている場合、そのクラスに応じてグローバルナビゲーションの1〜3番目のいずれかのリンクをカレント状態にします。「&
」を後ろに置くことで、特定の状況に応じたスタイルを簡潔に指定できるようになっています。
Sassとの比較
CSSネストは、標準のCSSでネスト構文を使う方法ですが、これに似た手法として、Web開発者の間で広く使用されているSass(サス、Syntactically Awesome Style Sheets)があります。
Sassとは
Sassは、CSSをより効率的に記述できる言語です。Sassを使うと、CSSよりも強力で柔軟なスタイルシートの作成が可能になります。例えば、変数を使って色やフォントサイズを再利用したり、ミックスインと呼ばれる機能を使って共通のスタイルを簡単に適用したりできます。
変数の使用例
$primary-color: #007bff;
.button {
background-color: $primary-color;
border: 1px solid darken($primary-color, 10%);
color: white;
}
.navbar {
background-color: $primary-color;
padding: 10px;
}
.alert {
border-left: 5px solid $primary-color;
background-color: lighten($primary-color, 40%);
padding: 15px;
}
この例では、$primary-color
という変数をボタンの背景色、ナビゲーションバーの背景色、アラートボックスの枠線や背景色に適用しています。
よく使う色とかを変数で管理しておくと、あとから変更がカンタン!
ミックスインの使用例
@mixin general-box($background-color) {
border-radius: 8px;
padding: 20px;
background-color: $background-color;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
}
.card {
@include general-box(#f8f9fa);
color: #333;
font-size: 16px;
}
.alert {
@include general-box(#ffeeba);
border: 1px solid #ffc107;
font-weight: bold;
}
.panel {
@include general-box(#e3f2fd);
margin-bottom: 15px;
font-family: Arial, sans-serif;
}
この例では、general-box
という名前のミックスインを定義し、引数には$background-color
を渡しています。それぞれの要素で、ミックスインを使って共通のボックススタイルを適用しつつ、card
、alert
、panel
にはそれぞれ固有のCSSプロパティも指定しています。
共通のスタイルはまとめてミックスインで管理!
Sassの基本や導入方法について知りたい方は、こちらの記事もぜひチェックしてみてください。
CSSネストとSassの違い
Sassの基本的な概要を理解したところで、次にCSSネストとSassがどのように異なるのか、その違いを見ていきましょう。
まず、CSSネストはネイティブCSSとして使用でき、ブラウザが直接解釈します。一方、Sassは、CSSのコードを書きやすくし、効率的に管理するためのツールです。ネスト構文をサポートしつつ、変数やミックスインなどを使った複雑なスタイルシートの管理が可能です。
次に、ブラウザ対応についてです。CSSネストは、最新のブラウザで対応が進んでいるものの、古いブラウザではサポートされていない記述があります。対照的に、Sassはコンパイル(専用のツールでCSSに変換すること)した後のCSSがすべてのブラウザで動作するため、古いブラウザでも問題ありません。
導入や学習コストにも違いがあります。CSSネストは特別なツールが不要で、学習コストも低いため、すぐに利用を開始できます。一方、Sassを使用するにはコンパイルツールが必要で、その設定や学習が必要になります。
これらの違いを以下の表にまとめました。
比較項目 | CSSネスト | Sass |
---|---|---|
構文と機能 | ネイティブCSSでネスト可能 | ネストに加え、変数やミックスインなどの高度な機能を提供 |
ブラウザ対応 | 最新ブラウザで対応、古いブラウザでは一部未対応 | コンパイル後のCSSはすべてのブラウザで動作 |
導入と学習コスト | 特別なツール不要、学習コストが低い | コンパイルツールが必要、学習コストが高い |
CSSネストは、近年の急速なCSSの進化に伴い、Sassの便利な機能に近づいてきており、シンプルなプロジェクトでは実用的な選択肢となりつつあります。とはいえ、クラス名の連結や関数、ミックスインといった高度な機能が必要な場合は、まだまだSassが活躍する時代が続きそうです。
もうひとつ大きな違いとして、「クラス名の連結」があります。以下で詳しく解説しますね。
Sassではクラス名を文字列として連結することができます。例えば、「BEM」のような命名規則を採用する場合、Sassではブロックやエレメントといったパーツごとに整理して効率的に命名できます。
.navbar {
background-color: #333;
color: #fff;
&__menu {
padding: 10px;
&__item {
margin: 5px 0;
list-style: none;
}
}
}
コンパイルされた後のCSSは以下です。
.navbar {
background-color: #333;
color: #fff;
}
.navbar__menu {
padding: 10px;
}
.navbar__menu__item {
margin: 5px 0;
list-style: none;
}
このように、SassではBEMの規則を活用しながらクラス名を簡単に連結できます。BEMについては、こちらのCodeGridの記事でわかりやすくまとめられています。
一方、CSSネストではクラス名の連結ができないため、BEMのような命名規則を効率よく活用することはできません。
BEM記法は少し古くなりつつある技術ですが、現在でも多くのプロジェクトで採用されている手法です。クラス名の連結が効率化につながる開発環境では、CSSネストだけでは少し不便に感じるかもしれません。こうした点も踏まえて、CSSネストの採用を検討してみてください。
まとめ
以上、CSSネストについて解説してきました。現時点では本格的な実用に向けてあと一歩というところですが、あと1〜2年もすれば、標準的に使える技術となるように思います。特に、IEの引退以降、CSSの進歩が格段に加速しており、今後の展開にも期待が高まります。
このような技術の進化が続く中で、最新情報をこまめにチェックしておくことが非常に大切だと感じます。この記事が、CSSについて理解を深める参考になれば嬉しいです。