【CSSテクニック】:not()セレクタで階層を跨いだ除外を実現

CSS の世界で :not() 擬似クラスって、実はめちゃくちゃ便利なのに、意外と過小評価されがちなんですよね。
多くの人は「同じ階層の要素を除外する」くらいにしか使ってない印象ですが、実はそれだけじゃないんです。
最近、このセレクタを使ったちょっと面白い課題にぶつかって、:not() の“階層を跨いでるように見える”使い方にハマりました。
背景と課題のシナリオ
こんな感じのHTML構造を想定しています:
<div class="post">
<p>Lorem ipsum dolor sit amet, sed alia expetenda liberavisse ut, id sit purto possim expetenda. In atqui aeque mandamus vis, sonet tamquam id his. Ne tota nobis his, eam tale sumo ut. Id odio ludus pro, sit ut autem ubique, no agam nemore pertinax per. Solum reque forensibus ius eu, an vix probo verear.</p>
<p>Lorem ipsum dolor sit amet, sed alia expetenda liberavisse ut, id sit purto possim expetenda. In atqui aeque mandamus vis, sonet tamquam id his. Ne tota nobis his, eam tale sumo ut. Id odio ludus pro, sit ut autem ubique, no agam nemore pertinax per. Solum reque forensibus ius eu, an vix probo verear.</p>
<p>Lorem ipsum dolor sit amet, sed alia expetenda <code>div .item</code> ut, id sit purto possim expetenda. In atqui aeque mandamus vis, sonet tamquam id his. Ne tota nobis his, eam tale sumo ut. Id odio ludus pro, sit ut autem ubique, no agam nemore pertinax per. Solum reque forensibus ius eu, an vix probo verear.</p>
<p>Lorem ipsum dolor sit amet, sed alia expetenda liberavisse ut, id sit purto possim expetenda. In atqui aeque mandamus vis, sonet tamquam id his. Ne tota nobis his, eam tale sumo ut. Id odio ludus pro, sit ut autem ubique, no agam nemore pertinax per. Solum reque forensibus ius eu, an vix probo verear.</p>
<p>Lorem ipsum dolor sit amet, sed alia expetenda liberavisse ut, id sit purto possim expetenda. In atqui aeque mandamus vis, sonet tamquam id his. Ne tota nobis his, eam tale sumo ut. Id odio ludus pro, sit ut autem ubique, no agam nemore pertinax per. Solum reque forensibus ius eu, an vix probo verear.</p>
<p>
<pre>
<code>
:root {
--theme-color: #ffe4c4;
--flex-list-col-num: 5;
--flex-list-column-gap: 1em;
--flex-width: calc((100% - var(--flex-list-column-gap) * (var(--flex-list-col-num) - 1)) / var(--flex-list-col-num));
}
#app {
padding: 20px;
}
</code>
</pre>
</p>
</div>
上の構造はWordPressの投稿内容なんですが、<code>
タグに背景色を付けたい一方で、<pre>
タグで囲まれたコードブロックの<code>
は除外したいっていう問題があって。つまり、段落内のインラインコードだけにスタイルをかけて、コードブロックには影響を与えたくないんです。
従来のアプローチとその限界
この問題を解決しようとすると、ふつうはこんな方法を試してみることが多いです:
- codeタグに直接スタイルを当てる
- preタグを除外する方法を試してみる
でも、この方法だと階層をまたいで選択することができません。
:not()
を使った「階層を跨ぐ除外」の実現方法
調べてみたら、:not()セレクタで完璧に解決できることが分かりました:
code:not(pre code) {
background-color: red;
}
このセレクタは「すべてのcodeタグを選ぶけど、preタグの中にあるcodeは除く」という意味です。
この手法が効果的な理由
:not()擬似クラスのすごいところは、単純なクラスやIDだけじゃなくて、複雑なセレクタも引数にできるってところです。だから、こんな感じで高度な選択ができるんです:
- 複数の階層をまたいで除外すること
- 親要素を踏まえてスタイルを調整する
この機能のおかげで、普通のCSSセレクタではできない「逆向きに選ぶ」方法ができちゃいます。
応用パターンと実用例
このテクニックはいろんな場面で使えます。例えば:
- インラインコードだけにスタイルをつけて、コードブロックには影響させない
- 特定の親要素の中の要素を除外したいとき
- 複雑な階層構造を操作したい場合
まとめ::not()
の可能性を引き出すには
:not()擬似クラスのこういう使い方は、CSSセレクタの柔軟さとパワフルさをよく表してますね。CSSの機能を工夫して使えば、一見ややこしい問題も案外シンプルに解決できるって分かりました。
次に「上方向に選択したい」や「特定の構造を除外したい」みたいなスタイルの問題にぶつかったら、ぜひ:not()セレクタのこの使い方を試してみてください。きっとビックリするような効果が出ますよ。