:not(.parent) > .target

:notを親/先祖に対して使う

タイトルの通り、「親/先祖が〜〜でない」要素を示すCSSを:notを使用して書く。

まず以下のようなHTML/CSSがあるとする。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
      :not(.parent) > .target {
        background-color: aquamarine;
      }
    </style>
</head>
<body>
    <div class="parent">親
        <div class="target">親の中にいる</div>
    </div>
    <div class="target">親の中にいない</div>
</body>
</html>

親の中にいるdivの背景は塗られず、親の中にいないdivの背景だけが塗られることになる

See the Pen parent_not by shinkats (@shinkats) on CodePen.

:not(.parent) > .target:notを使って「親が〜〜でない」要素のみを指定できていることがわかる。

:not == *:not

このときの:not部分に着目すると、:の前に何も記載されていないため、:not*:notと同じになる。

つまり:not(.parent)div:not(.parent)でもあるし、body:not(.parent)でもある。そのため>の有無で結果が変わってしまう。

子セレクタ>ではなく子孫セレクタの場合

親の中にいるdiv<div class="parent">の子であると同時に、bodyの子孫でもある。そのため、子セレクタをつけずに:not(.parent) .targetとすると、.parentでないbodyの子孫である.targetという条件に合致し、背景が塗られる。

See the Pen Untitled by shinkats (@shinkats) on CodePen.

常に子セレクタ>を使用して:notを使用するようにする。

.target:not()

:notを対象(子)自体につける

先ほどは:not*:not(.parent)と親/先祖に対して指定していた。しかし、.target:notと対象(子)自体を否定することでも「親/先祖が〜〜でない」要素を示すCSSを書くことができる。

この場合、子セレクタ>の有無で挙動が致命的に変わりはしない。なぜなら*:notと違って.target:notであれば、.target自体にはじめに絞っているから。div:notのつもりで指定したものがbody:notにまで効いているというようなことはおきない。

.target:not(.parent > .target)

.target:not(.parent > .target)と書くことで、.parentの子に.targetが続かない.targetという指定の仕方ができる。

つまり今回のHTMLで言うと、親の中にいないdivのみが対象になる。

.target:not(.parent .target)

.target:not(.parent .target)と書くことで、.parentの子孫に.targetがない.targetという指定の仕方ができる。

HTML次第では意図しない状況になる可能性もあるが、今回の場合は問題ないし、大概のケースで問題なく動くだろう。

とはいえ、子セレクタで明確に指定できる場合は子セレクタで明確に指定した方が良い。