Prevent :last-child from slowing you down 29 Mar Tweet

:first-child is a CSS selector that has been around since the CSS 2.1 spec . It is extremely useful and can be used effectively in various ways.

:last-child has finally made an appearance in CSS 3. One would think that selectors such as first and last child are pretty much the same and would be implemented at the same time. This is not the case and they have pretty big performance differences.



Why isn’t :last-child included within CSS2?

Jonathan Snook has an extremely informative article called Why we don’t have a parent selector. It is an interesting & in depth article that covers why :last-child is is so difficult for the browser to render and the article also has examples of :first-child vs :last-child .

Simply put, :last-child only functions correctly once the entire page has loaded. The way :last-child is rendered while the page is busy loading is executed differently throughout the different browsers.

Never use :last-child

I feel that last-child is not necessary in most cases. I say most cases to cover myself but I haven’t run into a situation where it’s a necessity. The only times I find I need first/last-child is when I’m styling some sort of list.

A typical example would be: padding-right and/or border-right applied to a navigation’s list items.

#nav li{border-right: 1px solid black; padding-right: 20px;}



The padding and border isn’t ideal on the last <li> element. This is what we want:



It’s pretty simple to solve with :last-child

#nav li:last-child{border-right: 0; padding-right: 0;}

This, however, won’t even work on LTE IE 8.

Use :first-child instead

:first-child is contained within the CSS2.1 spec and therefore is supported within IE 8 and has buggy support within IE 7. It would be a FAR better idea to make use of this.

Swap the properties around — Instead of border/padding right, set it to border/padding left.

#nav li{border-left: 1px solid black; padding-left: 20px;}

The menu example would look something like this:



You can solve this problem very easily without :last-child and have it supported by IE 7(buggy) and 8.

#nav li:first-child{border-left: 0; padding-left: 0;}

It’s very easy to convert your CSS into very efficient and cross browser friendly CSS — All you need to do is think about what it is you are trying to doing and imagine how else it could be achieved.

I wish it worked properly in IE 7

What is the deal with IE 7 and :first-child ? Very basically, IE7 will see a comment as the first child. In IE 7 li:first-child would not work on the following html:

<ul> <!-- This is a comment --> <li>One</li> <li>One</li> <li>One</li> </ul>

Now that we’ve established that things can be done more efficiently and in a cross-browser friendly fashion without too much difficulty, would it be possible to make :first-child function properly within IE 7 even if there are html comments throughout the html?

Your first thought might be:

No, it’s the way IE7 renders HTML. Let’s move on Your first thought

What selectors do IE7 support that are more reliable and could solve this simple problem? IE 7 supports adjacent selectors. I really love adjacent selectors and I think it is very under-rated. Chris Coyier has an article which explains adjacent selectors and other selectors too.

Basically, an adjacent selector selects the element that directly follows the targeted element. For example:

p + p{background: red}

This would select any paragraph element that has a preceding paragraph element. This would mean that the first paragraph element would not be selected because it does not contain any preceding paragraph element.

Pseudo-select via Non-selection

By this I mean that you could add a left border to every list item except the first. This could create the illusion of :first-child .

li + li{border-left: 1px solid black; padding-left: 20px}