[Fixed] CSS :last-child not working issues
Reasons why CSS :last-child is not working and how we can fix it!
Jan 1, 2023 | Read time 9 minutes🔔 Table of contents
Introduction
Using the :last-child
pseudo class can make our CSS more clean - eg not introducing uncessary classes or IDs.
Note: These pseudo-classes relate to the location of an element within the document tree - also known as tree-structural pseudo-classes
The :last-child
selector is great when your HTML is dynamic and you want to apply styles to the last element (eg highlight or change background color).
The :last-child
pseudo class will not work can be due to the following reasons:
- Incorrect use of the syntax
- Misunderstanding of
:last-child
and:last-of-type
- There are conflicting styles that will override your
:last-child
- Limited browser support
Reason 1 - Incorrect use of the syntax
The :last-child
pseudo class is used to select the very last element of a given parent container.
The syntax needs to start with a colon (:
) and the last-child
keyword. Often a few times where I see that my CSS is not working is that the spelling is not correct or I have double colons (::
).
Make sure that we are using the single colon (:
) and not the pseudo-element selector (::
)!
Pseudo elements are “fake” elements that gets created, but not seen in the HTML mark up. Some examples include: ::after, ::before, etc
Lets say we have the following HTML of a unordered list:
<ul>
<li>Jane Miller</li>
<li>Colin Drew</li>
<li>John Heinsohn</li>
<li>Tom Jones</li>
</ul>
Now we can select the last list item (“Tom Jones”) by using the following :last-child
selector and apply a solid orange border around it:
li:last-child {
border: 2px solid orange; /* Give border for "Tom Jones" */
}
Tip: Using :last-child with CSS classes will filter it!
A problem when I first used
:last-child
with CSS classes in front of the keyword is that I can’t seem to target the right element. For example,.my-class:last-child
does not work as intended!Adding a CSS class in front of the
:last-child
keyword just tells the browser to ONLY select the LAST element of a given container if that last element has the class.my-class
!So even if you think you have selected the “last child”, double check again. Because if your last child does not have the class applied to it, nothing will be selected!
Reason 2 - Misunderstanding between :last-child
and :last-of-type
A common misunderstanding of the :last-child
selector is that can filter out and select the last child type of a parent element.
Lets consider the following HTML structure - we want to select the last <p>
with .red
class:
<div class="home">
<p class="red">first</p>
<p class="red">second</p>
<p class="red">third</p>
<p class="red">fourth</p>
<span>blah</span>
</div>
A typical selector that you will use might be: .home .red:last-child
. This will not be correct, since .red:last-child
will refer to the <span>
element (the last element of .home
container).
Additionally since the <span>
element does not have a .red
class applied, our :last-child
CSS selector will do nothing!
.home .red:last-child { /*❌ Will not work! last-child refers to the span element*/
border: 1px solid red;
}
.home .red:last-of-type { /*✔️ Will select the last red class! */
border: 1px solid red;
}
As seen from the above code, to actually get what we want - selecting the last <p>
with .red
class, we have to use the :last-of-type
!
The difference between :last-child
and :last-of-type
is that :last-child
is less specific. What this means is that using :last-child
will always select the last element of a given parent element.
As for :last-of-type
it will select the last element of a type for a given parent element!
Reason 3 - conflicting styles that will override your :last-child
A common problem that you can encounter is the :last-child
styling is getting overwritten by another style.
In this case, we need to check the specifity of the element you are trying to style.
For example, you could have a styling that is more specific or using the !important keyword.
Lets consider the following example. We want to apply the last <span>
font to have color of red and we have the last selector using :last-child and the second using a class .my-span
<div class="container">
<span>XXX</span>
<span class="my-span">YYY</span>
</div>
.container :last-child { /*❌ Will not work! */
color: red;
}
.container .my-span { /*✔️ This is more specific than the above */
color: blue;
}
As we can see from the above code, targetting classes (.my-span
) will override our last-child styling. This is due to CSS classes being more specific than the pseudo classes!
What is CSS specificity?
Specificity is how browsers decide on which style to apply to which element. Based on the CSS selector is an order in which styles will be applied!
Generally, selectors with IDs will override classes. In turn, CSS selectors with classes will override pseudo-classes such as :last-child!
Reason 4 - Check browser support
Browser support is quite good for most modern browsers. There are issues however when you are trying to support this in Safari, when the :last-child
does not have any parent elements.
There are also support issues with IE6-8 versions. If you really need to support these versions then its best to have a look at javascript polyfills.
For example, we can use the lastChild property in JavaScript:
/* using the lastChild property */
document.getElementById("myList").lastChild.innerHTML;
/* OR the lastElementChild property */
const element = document.getElementById("myList")
let html = element.lastElementChild.innerHTML;
Tip: Using :last-child with ::before or ::after
We can combine the use of the
:last-child
pseudo class with pseudo elements such as ::before and ::after.In this case, the pseudo element needs to be used after the
:last-child
keyword. Using pseudo element before the last-child keyword would be redundant! Egp::after:last-child
just targets<p>
!As an example, consider the selector of
.home :last-child::before
- this would mean that we want to select thelast-child
of the.home
container element and target the::before
pseudo element.The HTML structure could look like the following:
<div class="home">
<p>first</p>
<p>second</p>
<p>third</p>
<p>
::before <!-- ✔️ Will select this element -->
"fourth"
::after
</p>
</div>
Additionally, when using pseudo elements, remember to also use the content
property!
.home :last-child::before{
content: ''; /*✔️ Need this for pseudo elements to work! */
color:red;
}
Browser support
:last-child
is well supported across most modern browsers. Theres issues with Safari when we trying to select the last-child with no parent.
Additionally if you need to support this with IE6-8, you will need to use JavaScript polyfills since this feature is not supported in those IE versions!
Summary
In this post, we went over a few reasons why using :last-child
is not working in your CSS. Using :last-child
is great for dynamic HTML - we do not care how many childen our container element has - just use last-child and it will select the very last child element!
However, using this pseudo class can have some problems. The issues stem from using incorrect syntax, a misunderstanding of how :last-child
behaves, having other classes override your last-child styings and browser support (mainly using Safari when trying to target elements with no parent).
Support is quite good across most modern browsers - if you need to support legacy browsers such as IE6-8, then its best to have a look at JavaScript polyfills!