{"id":8854,"date":"2011-04-20T06:18:54","date_gmt":"2011-04-20T13:18:54","guid":{"rendered":"http:\/\/css-tricks.com\/?p=8854"},"modified":"2021-11-12T14:44:49","modified_gmt":"2021-11-12T22:44:49","slug":"the-difference-between-nth-child-and-nth-of-type","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/the-difference-between-nth-child-and-nth-of-type\/","title":{"rendered":"The Difference Between :nth-child and :nth-of-type"},"content":{"rendered":"\n
Let’s assume this HTML:<\/p>\n\n\n\n
<section>\n <p>Little<\/p>\n <p>Piggy<\/p> <!-- We want this one -->\n<\/section><\/code><\/pre>\n\n\n\nThese will do the exact same thing:<\/p>\n\n\n\n
p:nth-child(2) { color: red; }<\/code><\/pre>\n\n\n\np:nth-of-type(2) { color: red; }<\/code><\/pre>\n\n\n\nThere is a difference though of course.<\/p>\n\n\n\n
Our :nth-child<\/code> selector above, in “Plain English,” means select an element if<\/em>:<\/p>\n\n\n\n- It is a paragraph element<\/li>
- It is the second child of a parent<\/li><\/ol>\n\n\n\n
Our :nth-of-type<\/code> selector, in “Plain English,” means:<\/p>\n\n\n\n- Select the second paragraph child of a parent<\/li><\/ol>\n\n\n\n
:nth-of-type<\/code> is… what’s a good way to say it… less conditional<\/em>.<\/p>\n\n\n\nLet’s say our markup changed to this:<\/p>\n\n\n\n
<section>\n <h1>Words<\/h1>\n <p>Little<\/p>\n <p>Piggy<\/p> <!-- We want this one -->\n<\/section><\/code><\/pre>\n\n\n\nThis breaks:<\/p>\n\n\n\n
p:nth-child(2) { color: red; } \/* Now incorrect *\/<\/code><\/pre>\n\n\n\nThis still works:<\/p>\n\n\n\n
p:nth-of-type(2) { color: red; } \/* Still works *\/<\/code><\/pre>\n\n\n\nBy “breaks”, I mean that the :nth-child<\/code> selector above is now selecting the word “Little” instead of “Piggy” because that element fulfills both 1) it’s the second child and 2) it’s a paragraph element. By “still works,” I mean that “Piggy” is still being selected because it’s the second paragraph under that parent element.<\/p>\n\n\n\nIf we were to add an <h2><\/code>\u00a0after that\u00a0<h1><\/code>, the :nth-child selector\u00a0wouldn\u2019t select anything at all<\/em>, because now the second child is no longer a paragraph so that selector finds nothing. The\u00a0:nth-of-type<\/code>\u00a0again still works.<\/p>\n\n\n\nI feel like :nth-of-type<\/code> is less fragile and more useful in general, despite :nth-child<\/code> being more common (in my eyes). How often do you think \u201cI want to select the second child of a parent if it just happens to be a paragraph.\u201d Possibly sometimes, but more likely you want to \u201cselect the second paragraph\u201d or \u201cselect every third table row,\u201d which are cases where :nth-of-type<\/code> is (again, in my eyes) a stronger choice.<\/p>\n\n\n\nI find most of my \u201ccrap, why isn\u2019t this :nth-child selector working?!\u201d<\/em> moments are because it turns out I\u2019ve tag-qualified the selector and that number child isn\u2019t really that tag. So when using :nth-child<\/code>, I find it\u2019s generally best to specify the parent and leave :nth-child<\/code> un-tag-qualified.<\/p>\n\n\n\ndl :nth-child(2) { } \/* is better than *\/\ndd:nth-child(2) { } \/* this *\/<\/code><\/pre>\n\n\n\nBut, of course, it all depends on the exact situation.<\/p>\n\n\n\n
Browser support for :nth-of-type<\/code> is fairly decent\u2026 Firefox 3.5+, Opera 9.5+, Chrome 2+, Safari 3.1+, IE 9+.<\/p>\n\n\n\nI\u2019d say if you need deeper support, jQuery would have your back (use the selector there, apply a class, and style with that class), but in fact jQuery dropped support for :nth-of-type. Seems weird to me. I heard it was because of low usage. If you want to go that route\u00a0here is a plugin to get them back<\/a>.<\/s>\u00a0jQuery 1.9 does now support :nth-of-type<\/code> again (back to IE 6), so that is an option.<\/p>\n\n\n\nRelated: don\u2019t forget about the awesome cousins :first-of-type<\/code>, :last-of-type<\/code>, :nth-last-of-type<\/code> and :only-of-type<\/code>. Learn more here.<\/a><\/p>\n\n\n\n