CSSの「型」を制する者はUIを制す:`:nth-of-type()` と `:nth-last-of-type()` の深淵
現場でCSSを書いていると、時々「なぜかスタイルが当たらない」「意図しない要素まで赤くなってしまった」という怪奇現象に出くわすことがあるだろう。特に `:nth-child()` を使っている時によく起きる悲劇だ。
「よし、リストの2番目にスタイルを当てよう」と `:nth-child(2)` を書いたら、その中に別の要素が紛れ込んでいて計算が狂った――そんな苦い経験はないだろうか?
今日は、そんな泥臭い「セレクタの罠」を華麗に回避し、堅牢なCSSを書くための武器として `:nth-of-type()` と `:nth-last-of-type()` を深掘りしていく。
—
なぜ `:nth-child()` ではなく `:nth-of-type()` なのか?
まず、この2つの根本的な違いを整理しておこう。
- `:nth-child(n)`: 親要素の中の「n番目の子要素」を指す。タグの種類は問わない。
- `:nth-of-type(n)`: 親要素の中で、「そのタグと同じ型の要素」だけをカウントして n番目を指す。
ブラウザのレンダリングエンジンは、`:nth-of-type()` に遭遇すると、DOMツリーを走査し「同じタグ名の兄弟要素だけを抽出したサブセット」を作ってからインデックスを計算する。この「フィルタリングしてからカウントする」という挙動こそが、UI構築において極めて強力な武器になるんだ。
—
実践:混合リストでの「型」の制御
たとえば、ブログ記事のレイアウトで、`p`タグと `figure`タグが混在しているとする。ここで「最初の2つの `p` タグだけに強調スタイルを当てたい」という要件が来たらどうする?
`:nth-child()` だと、途中に `figure` が入った瞬間にカウントがズレる。しかし、`:nth-of-type()` ならその心配は無用だ。
/ pタグだけを対象に、その中で1番目と2番目のものだけを抽出 /
article p:nth-of-type(-n+2) {
font-size: 1.2rem;
font-weight: bold;
color: #333;
}
/ 逆に、最後のpタグだけ特別扱いしたいならこれ /
article p:nth-last-of-type(1) {
margin-bottom: 0;
border-bottom: 2px solid #007bff;
}
このコードのポイントは `(-n+2)` という書き方だ。「最初の2つ」をスマートに指定するこのイディオムは、現場で頻出する。覚えておいて損はない。
—
現場で役立つ「後方からのカウント」という視点
`:nth-last-of-type()` は、UIコンポーネントの柔軟性を高めるために不可欠だ。
例えば、動的に増減する「カード型レイアウト」で、「最後のカードだけ下マージンを消したい」というケースは星の数ほどあるだろう。要素数が予測できない場合、`last-child` を使うのが定石だが、もしその直後に「広告」や「フッターリンク」のタグが動的に挿入されるような構造だったら?
/ 最後のカード(divタグ)だけ下マージンを消す /
.card-container div:nth-last-of-type(1) {
margin-bottom: 0;
}
このように「後ろからカウントする」というアプローチを持っておくことで、予期せぬDOM構造の変化に対しても、CSS側で「型」というセーフティネットを張れるようになる。
—
現場のチーフアーキテクトからの助言
最後に、実務で気をつけるべき「型」の罠について一つ伝授しよう。
`:nth-of-type()` は非常に便利だが、「同じ親の中に同じタグが複数ある」ことが前提だ。もし、マークアップの仕様変更で、途中でタグ名が変わってしまったり、ラッパー要素(`div`で囲むなど)が挿入されたりすると、カウントがリセットされる場合がある。
- 推奨スタイル: コンポーネントを設計する際は、可能な限りクラス名(`.card`, `.list-item`)でスタイルを制御するのがCSS設計の基本(BEMなど)だ。
- 使い所: しかし、CMSから吐き出されるHTMLや、Markdownから生成された構造など、「クラスを細かく振れないエリア」の微調整には、この `nth-of-type` 系が最強の解決策になる。
技術は常に「銀の弾丸」ではない。どの場面で、どの武器を抜くべきか。その判断基準に、今日の話が役立てば幸いだ。
さあ、エディタを開いて、DOMの構造を見つめ直してみてくれ。君が書くその一行が、明日誰かのCSSデバッグ時間を救うかもしれないのだから。

コメント