Kaya Toast
Kaya Toast

Reputation: 5503

How to use the :last-child selector?

I want to simply add a border-bottom to the last .slab

I tried a few things and I am unable to understand what is going on.

Case 1 - use .wrapper:last-child

If I try this on codepen.io or on Stackoverflow snippets, I don't get a border-bottom on last .slab

If I try this on JSFiddle or run the code separately in Chrome, I get a border-bottom on last .slab. However, if I uncomment <div class="something">New</div>, then the border-bottom on last .slab vanishes in both JSFiddle and on Chrome.

.wrapper {
    width: 10em;
    margin: 1em;
}
.wrapper:last-child {
    border-bottom: 1px solid #999;
}
.slab {
    background-color: #eee;
    border-top: 1px solid #999;
    padding: 1em;
}
<div class="wrapper">
    <div class="slab">Hello</div>
    <div class="slab">Hello</div>
    <div class="slab">Hello</div>
</div>
<!--<div class="something">New</div>-->

Case 2 - use .slab:last-child

Turns out this works everywhere - JSFiddle, Chrome, codepen.io and on Stackoverflow. But I thought the selection was really for the last-child of .slab and not the last .slab

.wrapper {
    width: 10em;
    margin: 1em;
}
.slab {
    background-color: #eee;
    border-top: 1px solid #999;
    padding: 1em;
}
.slab:last-child {
    border-bottom: 1px solid #999;
}
<div class="wrapper">
    <div class="slab">Hello</div>
    <div class="slab">Hello</div>
    <div class="slab">Hello</div>
</div>

Questions:

  1. Does .slab:last-child mean the last child of .slab or the last occurrence of .slab ?
  2. In case 1, why is the border-bottom vanishing after the introduction of an unrelated element .something ?
  3. What is the best way to apply border-bottom to the last .slab ?

Upvotes: 1

Views: 314

Answers (3)

Michael Benjamin
Michael Benjamin

Reputation: 371231

The :last-child structural pseudo-class selector applies to siblings of a parent. It is equivalent to :nth-last-child(1),

In terms of your code, you would apply :last-child to .slab to select the last sibling of parent div.wrapper.

If the last child of div.wrapper did not have a slab class, then the selector wouldn't match. It would do nothing.

If the :last-child were applied to the div children of div.wrapper, like this:

.wrapper > div:last-child { ... }

... then the selector would match the last child regardless of the class, id or other attributes. It would match any div. If the last child was not a div, the selector would do nothing.

If you wanted to match the last child of div.wrapper, regardless of anything – meaning it just needs to be the last child – then you could do something like this:

.wrapper > *:last-child { ... }

Without the > child combinator, let's say .wrapper *:last-child { ... }, the last child of all descendant parent elements would be matched.


When you select .wrapper:last-child, you're targeting the element with class wrapper that is the last child of its parent (presumably body, in this case).

If div.wrapper is the only child of its parent, then :last-child, :first-child, :only-child and most other structural pseudo-class keyword selectors would match.


For a better understanding of these selectors (and all others), refer to this section of the CSS spec: http://www.w3.org/TR/css3-selectors/#selectors

Upvotes: 2

BoltClock
BoltClock

Reputation: 723638

  1. Does .slab:last-child mean the last child of .slab or the last occurrence of .slab ?

    Neither. It matches an element that

    • has the "slab" class, and
    • is the last child of its parent.


    The last .slab within its parent may not necessarily be its last child. .slab:last-child will match if and only if both conditions are true for the given element.

  2. In case 1, why is the border-bottom vanishing after the introduction of an unrelated element .something ?

    Because then the last child of the parent of .wrapper becomes that other element. This element isn't unrelated to .wrapper — it's related to it by way of being its next sibling.

    The .slab elements within that wrapper never receive a border; the border is being applied to the .wrapper for as long as it is the last child of its parent. (Incidentally, the parent of .wrapper in your examples is implied to be body.)

  3. What is the best way to apply border-bottom to the last .slab ?

    You won't be able to do this reliably unless you can guarantee that the only possible children of .wrapper are .slab elements, in which case the class name then becomes quite irrelevant (but you can still include it in your selector so you avoid matching the last child of .wrapper when it's not a .slab).

Upvotes: 7

Paulie_D
Paulie_D

Reputation: 115046

last-child means exactly what is says...the very last element that is a child of a parent.

Not the last of class...the last element.

There is no last-of-class selector.

This: .slab:last-child means the last child that also has a class of .slab.

If it's not the last-child it won't apply and, equally, if it doesn't have a class of .slab it won't be selected.

Upvotes: 2

Related Questions