タイトル
本文
詳細
IT総合Wiki
| この記事の要点 |
|
子孫セレクタ (Descendant Combinator) は、ある要素の中にネストされている要素を選ぶための CSS セレクタです。区切りは半角スペースのみ。直接の子・孫・ひ孫を問わず全ての子孫がマッチします。
/* div の中にある全ての p (孫・ひ孫含む) */
div p {
color: red;
}
/* article 配下の見出しをまとめてスタイル */
article h1,
article h2,
article h3 {
font-family: 'Noto Serif JP', serif;
}
/* 複数階層 OK: .wrapper の中の .content の中の a */
.wrapper .content a {
text-decoration: underline;
}
| セレクタ | 意味 | マッチ例 |
|---|---|---|
div p | 子孫セレクタ (全階層) | div 内の p (孫も対象) |
div > p | 子セレクタ (直下のみ) | div の直下の p だけ |
h2 + p | 隣接兄弟セレクタ | h2 の直後の p 1つ |
h2 ~ p | 間接兄弟セレクタ | h2 以降の同階層 p 全部 |
div, p | グループ化 | div または p |
div.note | 同一要素への複合 | class=note を持つ div |
直下の p (A)
孫の p (B)
/* 子孫セレクタ: A も B もマッチ */
.outer p { color: red; }
/* 子セレクタ: A だけマッチ (B は孫なので除外) */
.outer > p { color: blue; }
/* h2 直後の p だけ (リード文の強調などに) */
h2 + p {
font-size: 1.1em;
font-weight: bold;
}
/* h2 以降の同階層 p 全部 */
h2 ~ p {
margin-left: 1em;
}
/* チェックボックスの状態でラベルを変える定番 */
input[type="checkbox"]:checked + label {
text-decoration: line-through;
color: #888;
}
/* div の中の全ての要素 (p, span, a, img ...) */
div * {
box-sizing: border-box;
}
/* 直下の全要素 */
div > * {
margin-top: 0;
}
/* リセット CSS の定番 */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
ブラウザは CSS セレクタを右から左へ評価します。.menu li a は "a 要素を全部探す → 親に li → 祖先に .menu" という順序。深いネストは古いブラウザで遅くなる可能性がありますが、現代のブラウザでは実用上ほぼ問題になりません。
むしろ問題は specificity (詳細度) です:
| セレクタ | 詳細度 (a, b, c) | 備考 |
|---|---|---|
p | 0, 0, 1 | 要素のみ |
.note | 0, 1, 0 | クラス 1つ |
div p | 0, 0, 2 | 要素 2つ |
.menu li a | 0, 1, 2 | クラス + 要素 2つ |
#main .item a | 1, 1, 1 | ID 含む → 強い |
!important | — | すべてに勝つ (最終手段) |
/* ❌ NG: 詳細度が高すぎて上書き困難 */
body div#main .container .card .header h2 span.title {
color: red;
}
/* ❌ NG: ネスト 5 段以上は保守性が悪い */
.sidebar .widget .list .item .link {
color: blue;
}
/* ✅ OK: BEM 命名で平坦化 */
.card__title { color: red; }
.sidebar-link { color: blue; }
jQuery セレクタは基本的に CSS と同じですが、jQuery 独自拡張もあります:
// CSS と同じ
$('div p').css('color', 'red');
$('div > p').css('color', 'blue');
$('h2 + p').css('font-weight', 'bold');
// jQuery 独自拡張 (純 CSS では不可)
$('div:contains("Hello")'); // テキスト含むもの
$('input:checkbox:checked'); // チェック済
$('p:first'); // 最初の p (CSS なら :first-of-type)
$('tr:eq(2)'); // 3 番目 (0 始まり)
// 現代の JS では querySelectorAll で OK
document.querySelectorAll('div p').forEach(el => el.style.color = 'red');
BEM (Block Element Modifier) は子孫セレクタを使わずにクラス名だけで構造を表現する命名規則です。詳細度が低く保ち、コンポーネント単位の差し替えが容易になります。
タイトル
本文
詳細
/* 全部単一クラスで詳細度 (0,1,0) に揃う */
.card { padding: 1em; border: 1px solid #ddd; }
.card--featured { border-color: gold; }
.card__title { font-size: 1.5em; }
.card__body { color: #333; }
.card__link { color: blue; }
.card__link--external::after { content: " ↗"; }
Q: div p と div, p の違いは?
A: スペースは子孫セレクタ (div の中の p)、カンマはグループ化 (div または p のどちらでも)。全くの別物です。
Q: 子孫セレクタは遅いと聞いた
A: 2010 年頃の話で、現代のブラウザではほぼ気にする必要なし。保守性 (詳細度・上書きやすさ) の方が重要です。
Q: Sass / SCSS のネストは子孫セレクタ?
A: Sass で .parent { .child { ... } } と書くと、コンパイル後は .parent .child (子孫セレクタ) になります。> .child なら子セレクタ。