【実務・中級編】 nth-last-child疑似クラスによる逆順選択 – CSS実践ガイド

やあ、お疲れ。最近、動的なリストのスタイリングで頭を悩ませていないか?
「リストの最後の3件だけ特別に背景色を変えたい」とか、「APIから何件降ってくるか分からない検索結果の、下から数えて特定の要素だけにボーダーをつけたい」なんて要件、実務では日常茶飯事だよな。

昔の僕らなら、JavaScriptでわざわざDOMの長さを計算してクラスを付与したり、サーバーサイドでゴニョゴニョと条件分岐を書いてクラスを出力したりしていた。だが、現代のCSSには、そんな泥臭いハックをスマートに一刀両断してくれる強力な武器がある。

それが今回解説する `:nth-last-child()` 疑似クラスだ。

名前からして「あぁ、`nth-child`の逆ね」とスルーしがちだが、こいつの仕様とブラウザの裏側の動きを正しく理解すると、コンポーネント設計の引き出しが一段と深まる。今日は、中級からワンランク上のシニアへステップアップしたい君に向けて、現場で即戦力となる知識を叩き込んでいこう。

—

1. `:nth-last-child()` の基本仕様と「逆順」のメカニズム

まずは基本の復習だ。`nth-child(n)` が「先頭から数えて何番目か」を指定するのに対し、`:nth-last-child(n)` は「末尾(一番最後の子要素)から数えて何番目か」を指定する。

ここでのポイントは、ブラウザがDOMツリーを解釈する際の「数え方」だ。

ブラウザは裏側でどう処理しているか?

ブラウザのレンダリングエンジン(BlinkやWebKitなど)は、親要素(Parent)が持つ子要素のコレクションを走査する際、通常の `nth-child` では「先頭(Index: 1)」からインクリメントしながら数えていく。
一方、`:nth-last-child()` では、ブラウザは子要素の総数(Total count)を把握した上で、末尾を起点(1)として逆算している。

つまり、動的に要素が追加・削除されて親の中身の数が変わろうとも、ブラウザ側が自動的に逆順のインデックスを再計算してくれる。これが、動的リストにおいてこの疑似クラスが最強たる所以だ。JavaScriptで要素数を監視する必要なんて、もうどこにもない。

—

2. 現場で使える実践パターン:数式(An+B)の魔術

`:nth-last-child()` も、通常のセレクタと同様に `An + B` という数式を受け付ける。この数式を「逆順」の文脈でどう脳内変換するか、ここがプロの腕の見せ所だ。

よくある実務のユースケースをいくつかコードベースで見ていこう。

パターンA:最後の3件だけに特別なスタイルを適用する

「APIから取得したタイムラインの、直近の3件(下から3つ)を目立たせたい」というケース。

/ リストの末尾から数えて3番目、2番目、1番目の要素を指定する /
.timeline-item:nth-last-child(-n + 3) {
background-color: #f0f7ff;
border-left: 4px solid #0066cc;
}

【解説】
`-n + 3` という数式は、「nに0, 1, 2…を代入したときの結果(3, 2, 1, 0…)」となり、末尾から数えて3番目までの要素にマッチする。これ、マジでよく使うから覚えておいて損はない。

パターンB:「最後以外」をすべて選択する(`:not` との組み合わせの卒業)

かつては `li:not(:last-child)` と書いてリストの区切り線(border-bottom)を調整していた時期もあったはずだ。しかし、`:nth-last-child()` を使えば、より直感的に記述できる。

/ 最後の子要素以外(つまり下から数えて2番目より前)にボーダーを付与 /
.list-item:nth-last-child(n + 2) {
border-bottom: 1px solid #e0e0e0;
}

【解説】
`n + 2` は「下から数えて2番目、3番目、4番目……(つまり最後以外すべて)」を指定する。`:not(:last-child)` よりも詳細度のコントロールがしやすく、数式の意味的にも「最後を除外する」のではなく「ここから上はすべて」というポジティブな指定ができる。

—

3. 【重要】「of S」構文(Selector List)の現在地と将来性

さて、ここからがチーフアーキテクトからのワンランク上の知見だ。
CSSSelectors Level 4で策定された機能に、`:nth-last-child(An + B of )` という構文があるのを知っているか?

これはどういうことかと言うと、「ただの子要素」ではなく、「特定のクラスを持つ要素だけに絞り込んだ上で、その中から最後から数えてN番目」を指定できるという、神がかった機能だ。

例えば、「 `.is-active` クラスがついている要素の中で、最後から数えて1番目のもの」を指定したい場合:

/ .is-active がついている要素の中で、最後のもの /
.item:nth-last-child(1 of .is-active) {
font-weight: bold;
}

ブラウザサポートの現状(2023年〜2024年以降)

この `of ` 構文、長らくSafariだけの隠し味状態だったが、主要なモダンブラウザ(Chrome, Firefox, Safari, Edge)すべてでサポートが完了している(Chromium 107以降、Firefox 113以降で完全対応)。
もう「将来の仕様」ではなく、「今すぐ現場で使える実用技術」だ。これを使えば、DOM構造が入り組んだ複雑なコンポーネントでも、余計なラッパーやJavaScriptの補助なしでスタイリングが完結する。

—

4. コピペで動く! 実務ライクな実践コード

最後に、実際のマークアップとCSSを組み合わせたサンプルを提示しよう。
掲示板やチャットアプリのメッセージリストを想定してくれ。最新のメッセージが下に溜まっていく構造だ。

  • こんにちは!
  • CSSの設計について相談があります。
  • `:nth-last-child`って実務で使えますか?
  • めちゃくちゃ使えますよ!

/ リスト全体の基本スタイル /
.chat-thread {
list-style: none;
padding: 1rem;
margin: 0;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}

.chat-message {
padding: 12px 16px;
margin-bottom: 8px;
background: #f8f9fa;
border-radius: 6px;
}

/ ————————————————–
ここからが :nth-last-child の真骨頂
————————————————– /

/ 1. 下から数えて最後のメッセージ(最新の投稿)だけハイライト /
.chat-message:nth-last-child(1) {
background: #e6f4ea;
border-left: 4px solid #34a853;
}

/ 2. 下から数えて2番目と3番目のメッセージに少しトーンを変化させる /
.chat-message:nth-last-child(n + 2):nth-last-child(-n + 3) {
background: #e8f0fe;
}

(※ 2つ目のセレクタのように、`:nth-last-child`をチェインさせることで「範囲指定(◯番目から〇番目まで)」を表現するテクニックも、CSSコーディングの現場では非常に重宝する)

—

まとめ

`:nth-last-child()` は、単なるマイナーな疑似クラスではない。動的なWebアプリケーション開発において、フロントエンドエンジニアのコードを劇的にクリーンにし、JavaScriptへの依存度を減らしてくれる強力なデザインツールだ。

「何件来るか分からない」という恐怖から解放され、CSSの数式とブラウザのエンジンを信じ切ること。それこそが、モダンCSSを自在に操るシニアエンジニアの思考法と言える。

さあ、今日のタスクのリスト表示のどこかに、こいつを早速組み込んでみないか? コードレビューで後輩から「おっ、これどうやってるんですか?」と聞かれるのが目に浮かぶようだ。がんばってくれよ!

コメント

タイトルとURLをコピーしました