こんにちは。シニアWebデザイナーとして長年現場でコードを書いてきましたが、CSSの擬似クラスの中でも、特に「かゆいところに手が届く」存在として信頼を寄せているのが :nth-last-of-type() です。
多くのWebデザイナーが :nth-child() や :nth-of-type() は日常的に使っていると思いますが、後ろから数える :nth-last-of-type() を活用できている人は意外と少ない印象を受けます。しかし、動的なコンテンツが増え、要素数が予測できない現在のWeb制作において、このセレクタは「条件分岐」に近い役割を果たし、コードの保守性を劇的に向上させてくれます。
今回は、実務で遭遇する「あるある」な課題を解決するための、プロフェッショナルな活用術を解説します。
なぜ :nth-last-of-type() が重要なのか
Webサイトのコンテンツは、CMS(WordPressなど)から出力されることがほとんどです。そのため、リストの要素数が変動するのは当たり前です。例えば、「最新記事一覧」が3つ表示されるときもあれば、5つ表示されるときもある。このような状況で、特定の要素にだけスタイルを当てたい場合、要素の総数をJavaScriptで計算するのは非効率ですし、メンテナンス性も悪いです。
:nth-last-of-type() は、「最後から何番目か」を指定できるため、要素の総数に依存せずにスタイルを制御できます。これは、CSS設計における「柔軟性」を担保するための強力な武器になります。
ケーススタディ1:最後の要素だけボーダーを消す
最も古典的ですが、今でも頻繁に使うのがこのパターンです。リストの区切り線として border-bottom を使用する場合、最後の要素にだけは線を引きたくないという要望は非常に多いです。
従来は :last-of-type を使うことが多かったのですが、場合によっては要素の構造が複雑で、単純に最後の子要素を消すとレイアウトが崩れることがあります。そこで :nth-last-of-type(1) を使うことで、意図を明確にできます。
CSSコード例
.list-item {
border-bottom: 1px solid #ccc;
padding: 16px 0;
}
/ 最後から1番目の要素のボーダーを消す /
.list-item:nth-last-of-type(1) {
border-bottom: none;
}
この書き方のメリットは、将来的にリストの構造が変わっても「末尾の要素」という条件が崩れないことにあります。:last-of-type と同等に見えますが、引数に値を渡せることで、より複雑な条件付けが可能になります。
ケーススタディ2:要素数に応じてレイアウトを変化させる
ここからがシニアデザイナーとしての腕の見せ所です。例えば、ボタンの配置やカード型のレイアウトで、要素が「2つあるときだけ」や「3つ以上あるときだけ」スタイルを変えたいというケースです。
例えば、ボタンが2つ並んでいるときだけ、それぞれの幅を50%ずつにしたい。しかし、ボタンが1つのときは幅を100%にしたい。これをメディアクエリを使わずにCSSだけで制御することができます。
CSSコード例
/ 2つのボタンが並んでいる状態を特定する /
.button:nth-last-of-type(2):first-of-type,
.button:nth-last-of-type(2):first-of-type ~ .button {
width: 50%;
}
/ 1つのボタンしかない状態 /
.button:only-of-type {
width: 100%;
}
このコードでは、:nth-last-of-type(2) が「後ろから数えて2番目」であると同時に、「最初から数えて1番目(:first-of-type)」である要素を指定することで、「合計で2つ要素が存在する」という条件をクリエイティブに作り出しています。これは「CSSの数式」とも言えるテクニックで、JavaScriptを使わずに複雑なUI制御を可能にします。
ケーススタディ3:特定の数以上の要素がある場合のみスタイルを当てる
「要素が3つ以上あるときだけ、特定の警告を表示する」あるいは「要素が多すぎる場合にリストの余白を詰める」といった制御も可能です。これは、n + 3 という数式を使うことで実現できます。
CSSコード例
/ リストが3つ以上ある場合、リスト同士の余白を狭くする /
.list-item:nth-last-of-type(n + 3) {
margin-bottom: 8px;
}
/ 2つ以下の場合は余白を広く保つ /
.list-item {
margin-bottom: 24px;
}
この書き方は、n + 3 が「3番目以降の要素」を指すことを利用しています。:nth-last-of-type(n + 3) と記述すると、後ろから数えて3番目、4番目、5番目……といった要素すべてが対象になります。つまり、リストの総数が3つ以上あれば、このスタイルが適用されることになります。
実務で意識すべき「セレクタの可読性」
プロのWebデザイナーとして、私が常に意識しているのは「コードの可読性」です。:nth-last-of-type() は強力ですが、複雑に書きすぎると他のメンバーがコードを読んだときに混乱を招きます。
例えば、:nth-last-of-type(3n + 1) のように複雑な数式を使う場合は、必ずコメントを残すようにしましょう。
CSSコード例
/ 3つ単位のグループの先頭要素を特定してスタイルを適用 /
.card:nth-last-of-type(3n + 1) {
margin-right: 0;
}
このようにコメントを添えるだけで、後から修正するエンジニアやデザイナーが「なぜこのセレクタを使っているのか」を一瞬で理解できます。CSSは、書くときよりも「読まれるとき」の方が多い言語です。だからこそ、こうした配慮がチームの生産性を大きく左右します。
パフォーマンスへの配慮
擬似クラス全般に言えることですが、あまりにも広範囲に適用したり、ネストが深すぎる構造に対して大量の擬似クラスを使用すると、ブラウザのレンダリングパフォーマンスに影響を与える可能性があります。
特に、数千件のDOM要素を持つリストに対して複雑な :nth-last-of-type() を使用することは避けましょう。通常の実務レベル(記事一覧やメニューなど)であれば全く問題ありませんが、パフォーマンスを意識したCSS設計という視点も忘れないでください。
今後のCSS設計の展望
近年では、:has() セレクタが登場したことで、CSSの表現力はさらに進化しました。:has() と :nth-last-of-type() を組み合わせることで、さらに強力な制御が可能になります。
例えば、「最後から2番目の要素に特定のクラスがある場合、その前の要素のスタイルを変える」といったことも、今ではCSSだけで完結します。
CSSコード例
/ 最後から2番目の要素が .active クラスを持っていたら、その前の要素の背景を変える /
.list-item:has(+ .list-item.active:nth-last-of-type(1)) {
background: #f0f0f0;
}
このように、従来のCSSではJavaScriptに頼るしかなかったUIの制御が、現代のCSSでは宣言的に記述できるようになりました。技術の進化を追いかけることは、シニアデザイナーとして最も重要なタスクの一つです。
まとめ:道具を正しく使いこなすということ
:nth-last-of-type() は、単なる「便利なセレクタ」ではありません。CSS設計における「柔軟性」と「堅牢性」を両立させるための、非常に洗練されたツールです。
実務においては、以下の3点を意識して活用してみてください。
1. 要素数が動的に変動するコンテンツには積極的に使う。
2. 複雑な条件分岐はコメントを残し、可読性を維持する。
3. :has() などの最新機能との組み合わせを視野に入れ、常にコードをアップデートする。
最初は難しく感じるかもしれませんが、一度この「後ろから数える」感覚を身につけてしまえば、コーディングのスピードと品質が格段に向上するはずです。
Webデザインの世界は日々変化しますが、こういった基礎的なセレクタの応用力こそが、長期的に活躍できるエンジニア・デザイナーの共通点だと確信しています。ぜひ、明日からの制作現場で試してみてください。
皆さんのコーディングライフが、より快適で創造的なものになることを願っています。

コメント