92

The issue lies within this CSS and HTML. Here is a link to jsFiddle with the sample code.

HTML

<ul>
    <li class"complete">1</li>
    <li class"complete">2</li>
    <li>3</li>
    <li>4</li>
</ul>

CSS

li.complete:last-child {
    background-color:yellow;
}

li.complete:last-of-type {
    background-color:yellow;
}

Shouldn't either of these lines of CSS target the last li element with the "complete" class?

This query in jQuery doesn't target it either:

$("li.complete:last-child");

But this one does:

$("li.complete").last();

li {
  background-color: green;
}
li.complete:first-child {
  background-color: white;
}
li.complete:first-of-type {
  background-color: red;
}
li.complete:last-of-type {
  background-color: blue;
}
li.complete:last-child {
  background-color: yellow;
}
<ul>
  <li class="complete">1</li>
  <li class="complete">2</li>
  <li>3</li>
  <li>4</li>
</ul>
Harry
  • 83,910
  • 24
  • 185
  • 203
Nej Kutcharian
  • 3,744
  • 4
  • 20
  • 27
  • @PatrickEvans What do you mean? http://api.jquery.com/category/selectors/ or more specifically http://api.jquery.com/last-child-selector/ – Nej Kutcharian Sep 25 '13 at 02:51
  • Does this answer your question? [How can I select the last element with a specific class, not last child inside of parent?](https://stackoverflow.com/questions/7298057/how-can-i-select-the-last-element-with-a-specific-class-not-last-child-inside-o) – fabpico Apr 12 '22 at 08:49

3 Answers3

150

The last-child selector is used to select the last child element of a parent. It cannot be used to select the last child element with a specific class under a given parent element.

The other part of the compound selector (which is attached before the :last-child) specifies extra conditions which the last child element must satisfy in-order for it to be selected. In the below snippet, you would see how the selected elements differ depending on the rest of the compound selector.

.parent :last-child{ /* this will select all elements which are last child of .parent */
  font-weight: bold;
}

.parent div:last-child{ /* this will select the last child of .parent only if it is a div*/
  background: crimson;
}

.parent div.child-2:last-child{ /* this will select the last child of .parent only if it is a div and has the class child-2*/
  color: beige;
}
<div class='parent'>
  <div class='child'>Child</div>
  <div class='child'>Child</div>
  <div class='child'>Child</div>
  <div>Child w/o class</div>
</div>
<div class='parent'>
  <div class='child'>Child</div>
  <div class='child'>Child</div>
  <div class='child'>Child</div>
  <div class='child-2'>Child w/o class</div>
</div>
<div class='parent'>
  <div class='child'>Child</div>
  <div class='child'>Child</div>
  <div class='child'>Child</div>
  <p>Child w/o class</p>
</div>

To answer your question, the below would style the last child li element with background color as red.

li:last-child{
    background-color: red;
}

But the following selector would not work for your markup because the last-child does not have the class='complete' even though it is an li.

li.complete:last-child{
    background-color: green;
}

It would have worked if (and only if) the last li in your markup also had class='complete'.


To address your query in the comments:

@Harry I find it rather odd that: .complete:last-of-type does not work, yet .complete:first-of-type does work, regardless of it's position it's parents element. Thanks for your help.

The selector .complete:first-of-type works in the fiddle because it (that is, the element with class='complete') is still the first element of type li within the parent. Try to add <li>0</li> as the first element under the ul and you will find that first-of-type also flops. This is because the first-of-type and last-of-type selectors select the first/last element of each type under the parent.

Refer to the answer posted by BoltClock, in this thread for more details about how the selector works. That is as comprehensive as it gets :)

Community
  • 1
  • 1
Harry
  • 83,910
  • 24
  • 185
  • 203
  • 4
    This is so silly but I think you're right. Hopefully they add this to the CSS4 spec. – Nej Kutcharian Sep 25 '13 at 02:58
  • @NejKutcharian: Yes, I think it has been in proposal for a long time. – Harry Sep 25 '13 at 02:59
  • @Harry I find it rather odd that: .complete:last-of-type does not work, yet .complete:first-of-type does work, regardless of it's position it's parents element. Thanks for your help. – Nej Kutcharian Sep 25 '13 at 03:03
  • @NejKutcharian: Ok got it. `.complete:first-of-type` works in the fiddle because it is still the first element of type `li` within the parent. Try to add `
  • 0
  • ` as the first element under `li` and you will find that `first-of-type` also flops. – Harry Sep 25 '13 at 03:06