treehouse : what would you like to learn today?
Web Design Web Development iOS Development

How nth-child Works

There is a CSS selector, really a pseudo-selector, called nth-child. Here is an example of using it:

``````ul li:nth-child(3n+3) {
color: #ccc;
}``````

What the above CSS does, is select every third list item inside unordered lists. That is, the 3rd, 6th, 9th, 12th, etc. But how does that work? And what other kinds of things can you do with nth-child? Let's take a look.

It boils down to what is in between those parentheses. nth-child accepts two keywords in that spot: even and odd. Those should be pretty obvious. "Even" selects even numbered elements, like the 2nd, 4th, 6th, etc. "Odd" selects odd numbered elements, like 1st, 3rd, 5th, etc.

As seen in the first example, nth-child also accepts equations in between those parentheses. The simplest possible equation? Just a number. If you put simply a number in the parentheses, it will match only that number element. For example, here is how to select only the 5th element:

``````ul li:nth-child(5) {
color: #ccc;
}``````

Let's get back to the "3n+3" from the original example though. How does that work? Why does it select every third element? The trick is understanding the "n" and algebraic equation that represents. Think of "n" as starting at zero and then a set of all positive integers. Then complete the equation. So the 3n is "3xn", and the whole equation together is "(3xn)+3". Now substituting in the zero and positive integers, we get:

(3 x 0) + 3 = 3 = 3rd Element
(3 x 1) + 3 = 6 = 6th Element
(3 x 2) + 3 = 9 = 9th Element
etc.

(2 x 0) + 1 = 1 = 1st Element
(2 x 1) + 1 = 3 = 3rd Element
(2 x 2) + 1 = 5 = 5th Element
etc.

Hey wait! That's the same as "odd", so probably don't need to use that one very often. But wait now. Haven't we exposed our original example as being overly complicated? What if instead of "3n+3", we used "3n+0", or even simpler "3n".

(3 x 0) = 0 = no match
(3 x 1) = 3 = 3rd Element
(3 x 2) = 6 = 6th Element
(3 x 3) = 9 = 9th Element
etc.

So as you can see, the matches are exactly the same, no need for the "+3". We can use negative n values, as well as use subtraction in the equations. For example, 4n-1:

(4 x 0) - 1 = -1 = no match
(4 x 1) - 1 = 3 = 3rd Element
(4 x 2) - 1 = 7 = 7th Element
etc.

Using "-n" values seems a little weird, because if the end result is negative there is no match, so you'll need to add to the equation to get it back positive again. As it turns out, this is a rather clever technique. You can use it to select the "first n elements" with "-n+3":

-0 + 3 = 3 = 3rd Element
-1 + 3 = 2 = 2nd Element
-2 + 3 = 1 = 1st Element
-3 + 3 = 0 = no match
etc.

Sitepoint has a nice reference guide, which includes this handy-dandy table which I'll shamelessly republish here:

n 2n+1 4n+1 4n+4 4n 5n-2 -n+3
0 1 1 4 - - 3
1 3 5 8 4 3 2
2 5 9 12 8 8 1
3 7 13 16 12 13 -
4 9 17 20 16 18 -
5 11 21 24 20 23 -

Browser Compatibility

nth-child is one of those rather unfortunate CSS attributes that is caught between nearly full cross-browser compatibility, except for completely zero support in IE, even IE 8. So when it comes to it's use, if the end result is "progressive enhancement" in some fashion (e.g. applying a cool color palette to table rows, for example), then by all means, go for it. But you probably shouldn't use it if you are doing something more important, like relying on it for site structure. For example, removing the right margin from every third box in a three by three grid of boxes, so they will fit properly.

One saving grace here is that if you are using jQuery, which supports all CSS selector including :nth-child, the selector will work, even in Internet Explorer.

Still not getting it?

I'm not a big fan of the phrase "I'm a visual learner". Of course you are, everybody is. Visual aids are enormously helpful in situations just like this. To help, I put together a little nth-child tester page. There, you can type in equations and see the results of what it selects below.

Also see this page of useful nth-child recipes for quick copy-and-paste code on the most common positional selecting needs.

It’s really nothing…
But testing your secondary school Mathematics…
Remember Sequences & Series.

2. Vincent

Thx for this!

Nice tip!

Your patience with the rest of us continues to amaze me Chris.

Well written, and more importantly, written in a manner that finally brings clear to me this concept.

And that was ‘without’ the phrase “I’m a visual learner”
:)

Thanks for taking the time to do this, and for your sharing. You’ve definitely paid-it-forward.

really nice post. Please place a retweet button in your posts so that it become easy to share on twitter.
Thanks.

• Not to sound like a wanker here, but retweet buttons take all the spirit out of Twitter if you ask me. If you like this (thanks!), then go up to the URL bar, copy the URL, go to Twitter, write a new tweet in your own words, and share the link.

You might even have a way easier way to tweet (for example on my Mac I use Tweetie and I just press Command-Return and I have a new tweet window).

This way:

1) It doesn’t rip you away from my site with a pre-filled, soulless tweet

2) People only do it if they sincerely want to share it, and do so with their own voice

• That doesn’t sound wankerish, that sounds considered, fair and responsible. Good work :)

• True, but share buttons don’t necessarily have to be all up in your face, and can prove useful for a lot of people.

touche.
nice post too :)
and nice testing page.

5. Wow, I have never even heard of that CSS selector. I thing the idea of progressive enhancement is a key selling point to most clients, except the first question out of their mouth is, “How will the site look on IE6 on a 800 x 600 screen resolution.” Love technology!

6. bill

In the meantime, just use jQuery.

One thing I find a bit counter-intuitive about :nth-child is that it uses all of the siblings when determining which elements to style, but will only style those that match the selector passed to it.

For example, if I have a page of text with p tags, a h1 tag and some h2 tags and, for some strange reason, I want to alternate the colours of the p tags, nth-child wouldn’t do this successfully.

p:nth-child(2n) would style…

h1
h2
p
p – This paragraph
p
h2
p
p – This paragraph.
p

…which is the 2nd and 5th paragraph. Not what I would expect.
Surely the only elements counted should be the p tags?

Apologies if this doesn’t read too well.

Turns out I need :nth-of-type instead.

• Not quite… You’d want to use adjacent sibling combinators:

h1 + p + p { color: red; }

demo

:nth-of-type still would require those headers and paragraphs to be wrapped in a parent of some kind.

8. Thanks for the Great Post Chris!

9. I was absolutely trying to do this “removing the right margin from every third box in a three by three grid of boxes, so they will fit properly” last week. And though I knew that I’d need to use js to get around IE, I was having trouble getting the equation/expression right. For some reason, I had missed the entire Algebra thing.

But thanks to your handy dandy refresher course, I get it now! ;-)

(I took the easy way out and just added the right margin measure to my #wrap div for time being.)

10. Matt

When it comes to a case where one browser will support it, and another won’t. I tend to go with the Javascript option. If it doesn’t work well cross browser, it won’t be used as a critical element anyway, so implementing it in JavaScript should be a safe way to go. Cross browser, but not critical.

11. Cool. I did not know you could do that with css. I might find a use for it in the future.

Seems like an awesomely simple way to handle zebra-striping tabular data.. aside, of course, from IE ruining the party as always.

I especially like the “first n elements” method.

Thanks Chris!

14. So nice – thanks for putting together this tutorial and the tester. I uses nth-child recently on a website to progressively fade out older Tweets.
`#tweets li:nth-child(2){opacity:.8;} `
Just a nice little look for good browsers.

15. DexTroN

Nice work explaining it for us who don’t remember our school math :D

btw it’s called “pseudo” and not “pseduo” like in your first sentence ^^

16. TeMc

Another short little example.

Say you want to style the top 3 and the top 10 in a special way of your top 100 list of something

```# HTML [ol id=ranking] [li]1. Lorem [li]2. Isum [li]3. etc. [/ol]```

```# CSS #ranking li { default:style; } #ranking li:nth-child(odd) { zebra:style; } #ranking li:nth-child(-n+10) { special: styling; } #ranking li:nth-child(-n+3) { special: styling even better; }```

You the cascasing and overwriting principle of CSS to style everything the way you want.

Pretty cool, huh ?

• That looks like it’d be by far the best way to use this selector.

I can’t imagine a lot of use for it otherwise, besides making viewing large chunks of the same type of tag a bit less repetitive/monotonous.

this is awesome, so many tutorials go way over the complexities surrounding nth-child.

But. Am i correct by saying, s’long as im requesting jquery into my site then the nth-child Will work, with no further work ?

Cheers

• TeMc

No, jQuery doesn’t “fix” anything that’s within your css files.

If you wanna use this the save way, for browsers that work with jQuery but not with CSS3, then you gotta do it in jQuery and not in CSS.

For example:

``` \$("tr:nth-child(odd)").css("background", "#ff0000"); ```

• TeMc

and:

• You can also have it apply classes instead, just for IE or browsers that don’t support this.

For example:
``` \$("tr:nth-child(odd)").addClass("nth-child-odd"); ```

I am using jQuery and CSS3 selectors. the nth-child is a very powerful future.

Thanks for your very nice tutorial.

19. I’m skinning something today for which this will be EXTREMELY helpful. you rock!

20. Antonio

Thanks for sharing this! Learning a ton from your articles!

If you want to unselectively grab all elements within another, you can use

element > :nth-child(blah){}

For instance, I am coding a site that will be updated by people who shouldn’t need to know CSS in the future, and in order for pictures and text to be pretty within overlays, I needed to style everything but the close button and an image to have particular margins. Fortunately, these were the first two elements within each overlay, so I could use

div.overlay > :nth-child(n+3){margin:0 10px 5px;}

Thanks for making me think about using nth-child!

22. anon

23. It’s superb info and i immediate twitt it on twitter to know others. Thanks

24. This is such great CSS, I just can’t believe that IE doesn’t support it. I mean I get why it might not render margin and padding the same (to name a few), but it really is awful that it doesn’t support such a technique. My life could be made a lot easier if I were able to use this for structuring sites…

Thanks anyway :)

It would be better to alternate the real CSS via JavaScript (thats `setStyle(s)` for MooTools, I don’t know the corresponding function in jQuery but it should be `.css(...)` or something like that) then using JavaScript directly.