262
<div class="commentList">
   <article class="comment " id="com21"></article>
   <article class="comment " id="com20"></article>
   <article class="comment " id="com19"></article>
   <div class="something"> hello </div>
</div>

I want to select #com19 ?

.comment {
    width:470px;
    border-bottom:1px dotted #f0f0f0;
    margin-bottom:10px;
}

.comment:last-child {
    border-bottom:none;
    margin-bottom:0;
}

That does not work as long as I do have another div.something as actual last child in the commentList. Is it possible to use the last-child selector in this case to select the last appearance of article.comment?

jsFiddle

isherwood
  • 58,414
  • 16
  • 114
  • 157
matt
  • 42,713
  • 103
  • 264
  • 397
  • linked: [select the “last child” with a specific class name in CSS?](https://stackoverflow.com/q/6401268/104380) – vsync Jul 23 '20 at 08:25

9 Answers9

296

:last-child only works when the element in question is the last child of the container, not the last of a specific type of element. For that, you want :last-of-type

http://jsfiddle.net/C23g6/3/

As per @BoltClock's comment, this is only checking for the last article element, not the last element with the class of .comment.

body {
  background: black;
}

.comment {
  width: 470px;
  border-bottom: 1px dotted #f0f0f0;
  margin-bottom: 10px;
}

.comment:last-of-type {
  border-bottom: none;
  margin-bottom: 0;
}
<div class="commentList">
  <article class="comment " id="com21"></article>

  <article class="comment " id="com20"></article>

  <article class="comment " id="com19"></article>

  <div class="something"> hello </div>
</div>
fodma1
  • 3,485
  • 1
  • 29
  • 49
Chris
  • 9,994
  • 3
  • 29
  • 31
  • 221
    It does not look at the class though, only the type, so if you happen to have non-articles with the same class you'll get unexpected results. – BoltClock Sep 04 '11 at 08:34
  • 1
    It works properly. However, if we need them to narrow down elements by class, it does not work again. http://jsfiddle.net/aliemreeee/a4H7f/2/ – Ali Emre Çakmakoğlu May 14 '14 at 13:38
  • 23
    based on these answers, I presume that there is no way to select `last-of-class`. – toobulkeh Jan 27 '15 at 15:52
  • 18
    not until CSS selectors level 4 is accepted and implemented by browsers, where you will have access to `:nth-match(selector)` and `:nth-last-match(selector)`. See http://www.w3.org/TR/selectors4/ for more detail. – Chris Feb 09 '15 at 22:55
  • 1
    Or rather, `:nth-last-child(An+B of selector)`, as `:nth-last-match()` was dropped long before that, but they haven't bothered to update the WD. See https://stackoverflow.com/questions/21167159/css-nth-match-doesnt-work/31415015#31415015 – BoltClock Jan 12 '18 at 19:42
  • 1
    Replace article with a div and this fails. – Johann Jun 26 '20 at 12:49
  • @AndroidDev It doesn't fail, it just changes which element gets targeted. – TylerH Nov 10 '20 at 14:40
  • `:nth-child(An+b of S)` is not implemented in any browser except for Safari (https://caniuse.com/css-nth-child-of) – yunzen Apr 30 '21 at 13:45
  • That doesn't work with tables, unless I applied it wrongly, but I'm sure I did not – Donovant Jul 19 '21 at 16:34
17

I guess that the most correct answer is: Use :nth-child (or, in this specific case, its counterpart :nth-last-child). Most only know this selector by its first argument to grab a range of items based on a calculation with n, but it can also take a second argument "of [any CSS selector]".

Your scenario could be solved with this selector: .commentList .comment:nth-last-child(1 of .comment)

But being technically correct doesn't mean you can use it, though, because this selector is as of now only implemented in Safari.

For further reading:

hurrtz
  • 1,871
  • 1
  • 19
  • 34
12

This can now be solved with careful use of :has(), specifically:

/* switch out the {class} below */
.{class}:not(:has(~ .{class}))

A similar technique also allows you to select anything but the last occurrence of a class in a container, or the last occurrence within a group of elements. See the snippet below for examples.

Note: has() is currently supported in Chrome, Edge and Safari, but not Firefox (Jan 2022)

/* last in group */
.class:has(+ :not(.class)) {
  background: pink;
}
/* anything but last in container */
.class:has(~ .class) {
  box-shadow: 0 0 0 1px #F00A;
}
/* last in container */
.class:not(:has(~ .class)) {
  background: #0F0A;
}
<div>
   <div class="class">not-last</div>
   <div class="class">not-last</div>
   <div class="class">last-in-group</div>
   <div>---</div>
   <div class="class">not-last</div>
   <div class="class">last-in-group</div>
   <div>---</div>
   <div class="class">last-class</div>
   <div>---</div>
</div>
som
  • 2,023
  • 30
  • 37
8

If you are floating the elements you can reverse the order

i.e. float: right; instead of float: left;

And then use this method to select the first-child of a class.

/* 1: Apply style to ALL instances */
#header .some-class {
  padding-right: 0;
}
/* 2: Remove style from ALL instances except FIRST instance */
#header .some-class~.some-class {
  padding-right: 20px;
}

This is actually applying the class to the LAST instance only because it's now in reversed order.

Here is a working example for you:

<!doctype html>
<head><title>CSS Test</title>
<style type="text/css">
.some-class { margin: 0; padding: 0 20px; list-style-type: square; }
.lfloat { float: left; display: block; }
.rfloat { float: right; display: block; }
/* apply style to last instance only */
#header .some-class {
  border: 1px solid red;
  padding-right: 0;
}
#header .some-class~.some-class {
  border: 0;
  padding-right: 20px;
}
</style>
</head>
<body>
<div id="header">
  <img src="some_image" title="Logo" class="lfloat no-border"/>
  <ul class="some-class rfloat">
    <li>List 1-1</li>
    <li>List 1-2</li>
    <li>List 1-3</li>
  </ul>
  <ul class="some-class rfloat">
    <li>List 2-1</li>
    <li>List 2-2</li>
    <li>List 2-3</li>
  </ul>
  <ul class="some-class rfloat">
    <li>List 3-1</li>
    <li>List 3-2</li>
    <li>List 3-3</li>
  </ul>
  <img src="some_other_img" title="Icon" class="rfloat no-border"/>
</div>
</body>
</html>
Ozzy
  • 8,244
  • 7
  • 55
  • 95
  • Note though this won't work if the floating elements are pushed onto the next line (i.e. not enough horizontal space to float-right/left) – Ozzy Jul 29 '13 at 01:03
  • `.some-class~.some-class` works great for me when only 2 elements repeated. – Meloman Apr 05 '18 at 11:39
7

Something that I think should be commented here that worked for me:

Use :last-child multiple times in the places needed so that it always gets the last of the last.

Take this for example:

.page.one .page-container .comment:last-child {
  color: red;
}
.page.two .page-container:last-child .comment:last-child {
  color: blue;
}
<p> When you use .comment:last-child </p>
<p> you only get the last comment in both parents </p>

<div class="page one">
  <div class="page-container">
    <p class="comment"> Something </p>
    <p class="comment"> Something </p>
  </div>

  <div class="page-container">
    <p class="comment"> Something </p>
    <p class="comment"> Something </p>
  </div>
</div>

<p> When you use .page-container:last-child .comment:last-child </p>
<p> you get the last page-container's, last comment </p>

<div class="page two">
  <div class="page-container">
    <p class="comment"> Something </p>
    <p class="comment"> Something </p>
  </div>

  <div class="page-container">
    <p class="comment"> Something </p>
    <p class="comment"> Something </p>
  </div>
</div>
A Friend
  • 1,420
  • 17
  • 22
  • Thanks for the answer. It helped. I have one question though. Why does ```.page.one .page-container:last-child``` not point to last child ? Why should we add comment also in the list of classes ? – Bharat Dec 22 '20 at 17:58
  • @Bharat It's hard to explain but I'll try my best. There's a hierarchy here; The `page` is the parent, `page-container`'s are the children, and the `comment`'s are the grandchildren. If you just do `.page.one .page-container:last-child` then you're getting the last child that has the class `page-container`, and not the last child that has the class `comment` because that was never specified. When using `:last-child` is doesn't look INSIDE the selected element for the last child, it looks AT the selected element to see if it's the last child. Does that make sense? – A Friend Dec 23 '20 at 19:03
6

The new :has() pseudo class (not yet supported by all browsers) lets you get pretty close to a solution:

.class:has(+ :not(.class))

The limitation is that this will find any element with .class which is followed by an element that doesn't have this class. But this would match the use case of the question.

wortwart
  • 3,139
  • 27
  • 31
1

What about this solution?

div.commentList > article.comment:not(:last-child):last-of-type
{
    color:red; /*or whatever...*/
}
lsblsb
  • 1,292
  • 12
  • 19
1

2023 way

After a bit of search i found this.

Works fine in chrome firefox edge and safari, not tested in other browsers

    /* target first element with class ".comment" */
    :nth-child(1 of .comment) {
        background-color: red;
    }

    /* target last element with class ".comment" */
    :nth-last-child(1 of .comment) {
        background-color: red;
    }
<div class="commentList">
 <div class="something"> hello </div>
 <article class="comment " id="com21">test</article>
 <article class="comment " id="com20">test</article>
 <article class="comment " id="com19">test</article>
 <div class="something"> hello </div>
</div>
Orlando
  • 19
  • 3
-2

There are two ways to select the last element of a class.

  1. Wrap your elements in a container element.

html:

<div class="container">
  <div class="member">Member</div>
  <div class="member">Member</div>
  <div class="member">Member</div>
<div>

css:

.container:last-child {
  color: red;
}
  1. If you don't want to wrap your elements within another element then you can leverage last-of-type.

html:

<div class="member">Member</div>
<div class="member">Member</div>
<div class="member">Member</div>

css:

.member:last-of-type{
 color: red;
}
Shamshad Zaheer
  • 221
  • 3
  • 11
  • This is exactly what he doesn't want, he wants to select a class "member" that is the last one. – – Leo Nov 15 '22 at 13:27