特定の親要素を持つ子要素だけcssを当てない方法

※本ブログの目的は個人の備忘録であり、コードは参考用として掲載しています。
実際に使用される際は、ご自身の環境で十分に動作確認を行ってください。
コードの利用によって生じたいかなる問題についても責任を負いかねますので、あらかじめご了承ください。

特定の親要素に基づいて、その子要素にスタイルを適用したくない場面はよくあります。

実際、このブログを作成する際、<pre>タグ内の<code>要素にはスタイルを適用したくない状況が出たので、それについての備忘録です。

必要のないCSSプロパティが付与されないように細かく調整するのは面倒ですよね。
そこで、いくつかの方法を紹介いたします。

:notセレクタを使った例

:not()擬似クラスを使うと、特定の要素を除外してスタイルを適用することができます。

/* pre要素の外にあるcode要素だけにスタイルを適用する */
:not(pre) > code {
  background-color: #f0f0f0;
  padding: 0.2em 0.4em;
  border-radius: 4px;
}

この方法では、「直近の親がpreではないcode」にだけスタイルが適用されます。

ポイントは、not(pre) > code子セレクタに指定することです。

なぜ:not(pre) codeではだめなのか?

preの中にあるcode全てに適用したいから、:not(pre) codeだと思いがちですが、これだと意図しない挙動になってしまいます。

たとえば、以下のHTMLを見てください。

<div>
  <pre>
    <code>これはpre内のコードです</code>
  </pre>
</div>

この場合、divはpreではないので、:not(pre)にマッチしてしまい、divの中にあるcodeにスタイルが当たってしまいます。

つまり、たとえpre内にあるcodeだとしても、スタイルが適用されてしまい、「pre内のcodeにはスタイルを当てたくない」という目的とズレてしまいます。

all: unsetを利用した例

preは中にdivなどのブロック要素をいれることができませんが、例えば以下のようにcodeがpreの孫要素だとしてもスタイルを当てたくない場合、:not()だと指定が難しいです。

<pre>
  <span>
    <code>これはpre内のコードです</code>
  </span>
</pre>

:not()セレクタでは「親がpreじゃない」ことしか見れないため、孫要素(間に何かが挟まっている場合)まで正確に除外するのは難しいです。

そのため、確実に「pre内のcodeにはスタイルを当てたくない」場合は、all: unsetを使う方法が有効です。

all: unsetは要素に適用されているすべてのスタイルをリセットするcssプロパティです。

code {
  /* まずすべてのcodeにスタイルを適用 */
  background-color: #f0f0f0;
  padding: 0.2em 0.4em;
  border-radius: 4px;
}
pre code {
  all: unset; /* preの中にあるすべてのcodeはリセットする */
  background-color: #000;
}
  • 一旦code全部にスタイルを当てる
  • そのあと、pre配下のcodeをリセットする

ただし、「親から継承されるはずのプロパティ」などもリセットされる強力なプロパティなので、使い所にはかなり注意が必要です。

まとめ

以上、特定の親要素を持つ子要素だけcssを当てない方法について考察してきました。

デモページをご用意しましたので、ぜひ参考にしてください。

目的にあった手段をうまく選んでいきましょう。