This is not the first time I see someone run into this problem so I decided to write few words on this topic. So far I haven’t run into situation or a real need that I have to use :nth-child selector (although it seems to be more popular) instead of :nth-of-type, how often do you think “I want to select the second child of a parent if it just happens to be a paragraph.”. Of course, in the current version of your html you might can make your code to work, your java script or your css, but that can be untriggered bomb for anyone that will inherit your code and which is even worse that anyone can be you in the future.
It’s best to explain this with a practical example. Let’s say that we have a scoreboard with results from an athletic track race. Now we have a requirement that we need to color differently the first, second and third place to resemble the appropriate award – gold, silver or bronze. Let’s say that we have this html to display the result table
Implementation using :nth-child selector
This selector’s name implies that should be the logical choice, and for the current version of the html it will work perfect, and we’ll get the wanted award colors in the scoreboard. With this CSS we are selecting the first, second and third div in a section and apply the proper coloring.
The results? As we expected!
This is the working example you can try yourself: https://jsfiddle.net/szLed4pp/7/
This is ok for now but what is someone adds another element in the section, lets say the client wants to have a heading/title that will describe the type of the event that the results are for, and after you add the h3 element your scoreboard html will look like this:
Now we have the description header on our page but our CSS is broken and it’s now functioning as we expect it to do.
This is the working example you can try yourself: https://jsfiddle.net/szLed4pp/10/
But why our CSS is not working after we added the h3 element?
That is because nth-child has strict conditions that the we are selecting the child at that position and the child at that position must be of the specified type, in our case div. After we added the h3 element the child at the first position is h3 so the first selector will not find any elements, the second selector will actually find the first div because that is the second child and it’s of type div, same applies for the third selector.
Implementation using :nth-of-type selector
Let’s see how we can implement the same requirement by using nth-of-type instead of nth-child selector. The CSS will be very similar to the previous one and we’ll use the same initial HTML for the example.
The results? Again, as we expected!
This is the working example you can try yourself: https://jsfiddle.net/dL729cpv/6/
And now let’s say we have the same requirement, that the client wants to add heading/title to the scoreboard describing the event type. After the update, the element will look exactly as in the previous implementation.
Now, let’s see the results after we made this update according to the client requirements.
This is the working example you can try yourself: https://jsfiddle.net/dL729cpv/8/
Nothing is broken, everything works fine! This is because the nth-of-type selector is counting only the div elements (as in our example) and if add any other elements they will not be taken into consideration.
As you could see :nth-of-type is more practical and can be more of use than :nth-child. Also it seems to be more safe for further development and protects you (more) from code breaking after applying HTML updates.
:nth-of-type is supported by these Browsers: Firefox 3.5+, Opera 9.5+, Chrome 2+, Safari 3.1+, IE 9+… and also by jQuery 1.9…
So, remember this article next time when you say “Why is my :nth-child selector not working” 🙂