230
<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
  • 52,576
  • 15
  • 105
  • 143
matt
  • 40,185
  • 99
  • 257
  • 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

6 Answers6

273

: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,287
  • 1
  • 24
  • 46
Chris
  • 9,430
  • 3
  • 27
  • 31
  • 193
    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
  • 16
    based on these answers, I presume that there is no way to select `last-of-class`. – toobulkeh Jan 27 '15 at 15:52
  • 17
    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
  • 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
10

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,721
  • 1
  • 18
  • 33
6

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,027
  • 7
  • 51
  • 93
  • 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
5

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,315
  • 15
  • 21
  • 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
0

What about this solution?

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

if the last element type is article too, last-of-type will not work as expected.

maybe i not really understand how it work.

demo

Allen
  • 1,789
  • 2
  • 12
  • 20