CSSに書いた色分けの設定がズレた犯人は自動広告だった

ランキング記事で「1位は金・2位は銀・3位は銅」みたいな色分けをしていたはずなのに、いつの間にか色が1つ後ろにズレていた。CSSは何度見直しても正しい。犯人を探していったら、記事本文に自動で入るAdSense広告でした。
今日はWP保守のクライアントさんのサイトを見て回っていた
先日、WP保守で運用しているクライアントさんのブログを一通り眺めていて、あれ?と気づきました。ランキング形式で書かれた記事の色分けが、なんだか順番とズレている。1位のはずが色なし、2位に金色、3位に銀色、というふうに1つずつ後ろに寄っている感じ。
公開時のプレビューではちゃんと1位に金色が付いていました。なのに本番で見ると1つズレている。ブラウザのキャッシュを疑ってみたけれど変わらない。CSSも変更していない。何が起きたんだろう、と首をかしげました。
犯人はAdSenseの自動挿入広告だった
本番のページを開いて、ブラウザの検証ツールで実際のHTML構造を見てみたら、原因がわかりました。ランキングの1位を表示している要素の1つ上に、AdSenseの広告ブロックがこっそり挿入されていたんです。
AdSenseの「自動広告」を有効にしていると、Googleが「ここに広告を入れると読まれそう」と判断した位置に、勝手に広告要素をねじ込んでくる仕組みになっています。今回のクライアントさんはそれをONにしていた。
で、問題のランキングのCSSはこんな書き方でした。
.ranking-item:nth-child(1) { color: gold; }
.ranking-item:nth-child(2) { color: silver; }
.ranking-item:nth-child(3) { color: #cd7f32; }
※「:nth-child(n)」とは、CSSで「親要素から見てn番目の子要素」を指す書き方です。親の中にある子要素をタグの種類に関係なく順番に数えて、n番目に当たるものにスタイルを当てます。
ここが落とし穴でした。:nth-child は「親から見て何番目の子か」を数えるので、途中に別のタグ(今回はAdSense広告のブロック)が割り込むと、順番がまるごとズレます。
たとえるなら、学級写真で背の高い順に並んでいたクラスに、朝の会で急に転校生(AdSense)が列の途中に割り込んできて、そこから数え直したら「背の高い順のはずが、なぜか2番目の子が先頭に来てる」みたいな話です。
解決は :nth-of-type に置き換えるだけ
直し方はシンプルでした。:nth-child を :nth-of-type に置き換えるだけ。
.ranking-item:nth-of-type(1) { color: gold; }
.ranking-item:nth-of-type(2) { color: silver; }
.ranking-item:nth-of-type(3) { color: #cd7f32; }
※「:nth-of-type(n)」とは、CSSで「同じタグの中でn番目のもの」を指す書き方です。:nth-child と違って、別のタグは数に含めません。
今回のランキング要素はすべて同じdiv(ranking-itemクラス付き)なので、:nth-of-type にしておけば、途中に広告divが割り込もうがなにが挟まろうが、ranking-item だけを数えて色を当ててくれます。
同じつまずきを防ぐには
今回の学びは大きく2つでした。
:nth-of-type を使う::nth-child は途中に別のタグが挟まると数え方がズレるので、ランキングやリストで色分けするときは :nth-of-type の方が事故が少ないです。広告そのものはサイトの収益源なので止められないし、自動配置は便利で使いたいところ。だからこそCSS側で「途中になにが入っても壊れない書き方」で受け止めておくのが健全なんだな、と今回あらためて思いました。
同じところでつまずく人が減ればうれしいです。