A painting of a lone figure standing in a sickly creek in front of a large tree decorated with sticks, rags and skulls

“Last” CSS pseudo-selectors are another useful way of detaching presentation from markup: rather than littering our HTML with classes to try to define what happens to the last instance of elements inside them, which would force us to move and reapply those classes when the content changes, we use a selector that will only ever be applied to the last element without changing our markup at all.

In order to use last-child effectively, we need to understand the child and sibling relationship in CSS. Let’s say we have the following markup:

    <p>Along the shore the cloud waves break,</p>
    <p>The twin suns sink behind the lake,</p>
    <p>The shadows lengthen</p>
    <p>In Carcosa.</p>
    <p>Strange is the night where black stars rise,</p>
    <p>And strange moons circle through the skies,</p>
    <p>But stranger still is</p>
    <p>Lost Carcosa.</p>

If we wanted to indent the last paragraph in each <div> element, we could do many things: apply a repeated inline style (extremely wasteful, difficult to maintain or change, and very time-consuming); a repeated class (better, but still uses a lot of time to create, apply or change), nth-child, or the best option: last-child

article p:last-child { text-indent: 2rem; }

Which will result in:

Along the shore the cloud waves break,

The twin suns sink behind the lake,

The shadows lengthen

In Carcosa.

Strange is the night where black stars rise,

And strange moons circle through the skies,

But stranger still is

Lost Carcosa.

Note that this is only true if a paragraph is indeed the last child of each element. If each ends with a horizontal rule instead:

    <p>In Carcosa.</p>

…then paragraphs are not the last child of the element, and the rule will be ignored. In such cases, the last-of-type pseudo-selector might be more useful.

Last Chance to See

The last-of-type selector finds the last occurrence of the type of element, and modifies that.

article p:last-of-type { text-indent: 2rem; }

This rule would have the same effect on the content as last-child, in this case. Note that both of these selectors can be used in combination with others: modifying the last occurrence of a class, for example.

A good use-case for last-of-type is removing a visual effect from the last item that is applied to every other element. For example, a navigation bar:

    <a href="#">Home</a>
    <a href="#">About Us</a>
    <a href="#">Products</a>

Our design styles each link with a border on its right side, intended to separate the link from it’s neighbour:

nav a { border-right: 1px solid #000; }

The problem being that the last link will also have a border on it’s right side. Visually, these vertical lines read as “there is a link that follows”; in the case of the last link, that’s not true. We could use last-child to eliminate this:

nav a { border-right: 1px solid #000; }
nav a:last-child { border-right: none; }

Even better, this could be written in a single line of CSS, by joining it with nav a:not(:last-child) { border-right: 1px solid #000; }

Painting by Tyler Bartley

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/PWJOMb