こんにちは。プロダクトのフロントエンドを預かる立場として、日々君たちの書くコードを見ているが……おっ、今日はCSSのセレクタ、それも少しマニアックで実務でめちゃくちゃ効く `:nth-last-of-type` について気になっているのか。素晴らしい着眼点だ。
CSSのセレクタって、基礎を覚えた後についついクラス(`.class`)ばかりに頼りがちになる。だが、大規模なWebアプリケーションの保守や、動的に要素が増減するUIコンポーネントを組むとき、構造的な疑似クラスを使いこなせるかどうかでコードの美しさとメンテナンシビリティが劇的に変わるんだ。
今日は、その中でも「後ろから数える」という少しひねった、しかし現場では神のような救世主となる `:nth-last-of-type` について、ブラウザの裏側の動きも含めて徹底的に叩き込んでやろう。
—
1. `:nth-last-of-type` とは何か?(仕様の再確認)
まず、基本の定義からいこう。
`:nth-last-of-type(an + b)` は、「同じ親要素の中にある、自分と同じタグ名の要素たちを、末尾(後ろ)から数えて特定の順番にマッチさせる」 疑似クラスだ。
ここでよくある誤解を解いておく。
よく似た兄弟に `:nth-of-type` があるが、あちらは「先頭から」数える。それに対して `:nth-last-of-type` は 「末尾から」 カウントアップする。
そして非常に重要なのが、「of-type」 という部分だ。これはいわゆるクラス名や属性ではなく、HTMLの「タグ名(`
` など)」 を基準にグループ化してカウントする。ここを混同すると、期待通りのスタイルが当たらなくて深夜に頭を抱えることになるので注意してほしい。
ブラウザは裏側でどう処理しているか?
少しエンジニアっぽい話をしよう。ブラウザのレンダリングエンジン(BlinkやGeckoなど)は、DOMツリーを構築した後、スタイルを適用する「スタイル計算(Style Recalculation)」のフェーズに入る。
このとき、ブラウザは親要素(Parent Node)が持つ子要素のリストを走査するわけだが、`:nth-last-of-type` が指定されていると、末尾の要素から逆順にインデックスを付与していく。
「後ろから数える」という仕様上、DOMの末尾から数え上げるため、動的に要素が追加・削除されるリスト(例えばチャットのメッセージログや無限スクロールのタイムラインなど)において、「常に最後のN個」を効率よく特定できるという強力なメリットがあるんだ。
—
2. 実務でなぜこれが「神」なのか?(利用シーン)
実務でフロントエンドを書いていて、こんな絶望を味わったことはないか?
> 「CMSから出力される記事詳細の本文(`article`内)で、最後の3つの段落だけに特別な余白や注意書きのスタイルを当てたい。でも、マークアップ構造が動的すぎてクラスを付与するフックがない……!」
こういうとき、クラス名に頼ろうとすると、JavaScriptでゴリゴリDOMを操作してクラスを付与するか、CMS側のレンダリングロジックを書き換えるハメになる。どちらも保守性を下げる悪手だ。
ここで `:nth-last-of-type` の出番だ。これを使えば、HTMLを一行も汚さずに、純粋なCSSだけで「後ろから〇番目」を正確に射抜くことができる。
—
3. 実践!コピペで使えるキレイなサンプルコード
百聞は一見にしかずだ。実務でそのまま使える、洗練されたコードパターンをいくつか見せよう。
パターンA:可変長のリストで「最後から3番目以内」の要素にスタイルを適用する
例えば、検索結果や通知リストなどで、下から数えて直近の3件を目立たせたいときのイディオムだ。
- システムメンテナンスのお知らせ(古い)
- プロフィール画像が更新されました
- 新しいメッセージが届いています(直近3)
- セキュリティアラート(直近2)
- タスクの期限が近づいています(直近1)
.notification-list {
list-style: none;
padding: 0;
margin: 0;
}
.notification-list li {
padding: 16px;
border-bottom: 1px solid #eee;
}
/
後ろから数えて3番目、2番目、1番目(つまり最後の3つ)の
-n + 3 は、「3以下」を意味するおなじみの数式だ
/
.notification-list li:nth-last-of-type(-n + 3) {
background-color: #f0f7ff;
border-left: 4px solid #0066cc;
}
/ 一番最後の要素だけ下線を消すなどの微調整も簡単 /
.notification-list li:last-of-type {
border-bottom: none;
}
パターンB:異なるタグが混ざる複雑なコンポーネントでの罠を回避する
実務で一番ハマるのがこれだ。フォームのバリデーションメッセージなどで、`
` タグや `` タグが混在しているケースを考えてみよう。
会社用メールアドレスを入力してください。
※メールアドレスの形式が正しくありません。
ここで「最後の段落(`
` タグ)」だけに特別なスタイルを当てたいとする。
素人がやりがちなミスが `:last-child` や `:nth-last-child(1)` を使うことだ。これらは「要素の種類を問わず親から見て最後の子供」を選ぶため、もし将来的に `
しかし、`:nth-last-of-type` ならば安心だ。
/
親要素(.form-group)の中にある
タグの中で、後ろから数えて1番目(最後)のものだけを選択
/
.form-group p:nth-last-of-type(1) {
font-weight: bold;
color: #e53e3e; / エラーメッセージを赤字にするなど /
}
この書き方をしておけば、仮に上に他のタグが挿入されようとも、`
` タグの中での「最後尾」を確実にターゲットし続けることができる。これがプロの堅牢性というやつだ。
—
4. シニアから後輩へ送る、実務での注意点とTips
最後に、現場でこのセレクタを扱う上での「プロの心得」をいくつか授けておこう。
1. 過度なネストや複雑な数式は避ける
`:nth-last-of-type(4n + 1)` のような複雑な数式は、パッと見で何をしているか他のエンジニアが理解するのに時間がかかる。どうしても複雑な条件が必要になる場合は、CSSだけで頑張りすぎず、クラスを付与する設計へのリファクタリングを検討してくれ。「読めるコード」は正義だ。
2. 「-of-type」と「-child」の違いをチームで共通認識にする
レビューをしていて一番多いのが、タグの種類を意識せずに `:nth-last-of-type` を使ってしまい、意図した挙動にならないケースだ。HTMLの構造(どのタグの兄弟なのか)を必ず頭に描いてからコードを書く癖をつけよう。
CSSの疑似クラスは、DOM構造を深く理解していればいるほど、君の強力な武器になる。
今回学んだ `:nth-last-of-type` も、ただの機能の知識として終わらせず、次に見るデザインカンプや実装の場で「あ、ここは後ろから数えたほうがキレイに組めるな」とパッと引き出しから取り出せるようになってくれ。
さて、今日の講義はここまでだ。お互い、イケてるコードを書こうぜ!

コメント