What is the difference between p:nth-child(2)
and p:nth-of-type(2)
?
As per W3Schools CSS Selector Reference:
p:nth-chil
Assume we have following HTML:
<div id="content">
<p>a1</p>
<span>a2</span>
<p>a3</p>
<span>a4</span>
</div>
1) #content p:nth-child(2)
-- applies to 0 elements
because p:nth-child(2)
requires it be the second child and that the tag is p
, but actually the tag is a <span>
.
2) #content *:nth-child(2)
-- apples to <span>a2</span>
because *:nth-child(2)
only requires it be the second child, not require the tag name. *
can be any tag name.
3) #content p:nth-of-type(2)
. -- applies to <p>a3</p>
because p:nth-of-type(2)
means the second one in the <p>
node list.
4) #content *:nth-of-type(2)
. -- applies to <p>a3</p>
and <span>a4</span>
because *:nth-of-type(2)
only requires the second one in the same tag node list.
The other answers hightlighted the main difference between both selectors which is the fact that nth-child
will consider all the elements inside the same container (siblings elements) and nth-of-type
will consider all the elements with the same type inside the same container.
The
:nth-child(an+b)
pseudo-class notation represents an element that has an+b-1 siblings before it in the document treerefThe
:nth-of-type(an+b)
pseudo-class notation represents an element that has an+b-1 siblings with the same expanded element name before it in the document treeref
From this we can add another important difference between both selectors which is the fact that nth-of-type
is generally used with a tag selector whereas nth-child
doesn't need a tag selector. In other words, nth-of-type
can select more than one element but nth-child
can select only one element. Adding a tag selector with nth-of-type
will restrict the selection to one element and adding a tag selector to nth-child
will simply add more restriction to the one element we are targeting.1
This selector will select the 2nd child of .container
.
.container :nth-child(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
This is the same selector as above but we add a tag restriction: Find the 2nd child of .container
, if it's a p
tag then select it.
.container p:nth-child(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
If we change p
with h1
nothing will be selected because the 2nd child isn't a h1
:
.container h1:nth-child(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
This selector will select the 2nd p
and the 2nd h1
. nth-of-type
will behave like nth-child
after grouping elements by the same type.
.container :nth-of-type(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
So we select the 2nd child inside this:
<div class="container">
<p>aaa</p>
<p>aaa</p> <-- this one -->
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
</div>
Then the 2nd child inside this:
<div class="container">
<h1>title</h1>
<h1>title</h1> <-- this one -->
</div>
Adding a tag selector will simply restrict the selection to only one group of element:
.container p:nth-of-type(2) {
border:1px solid red;
}
.container h1:nth-of-type(2) {
border:1px solid green;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
If your container contains only one type of element both selectors will for sure give the same result but will not behave the same (i.e. the alogirthm behind will be different). You may also notice that if you remove the tag selector from both you will also have the same result:
.container :nth-of-type(2) {
border:1px solid red;
}
.container :nth-child(2) {
color:red;
}
/* The below will also select the same
.container p:nth-child(2)
.container p:nth-of-type(2)
.container *:nth-child(2)
.container *:nth-of-type(2)
*/
<div class="container">
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
</div>
Another difference (this is a personal thought) may be the performance of both. nth-child
can be faster since it consider all the siblings elements at once so it's like we will have one loop to check all the elements. nth-of-type
need to consider different type of elements not at the same time so we will probably have more processing thus it's slower (This is my own conclusion based on how both works. I have no formal proof of it).
1: I am considering a selection inside one container using an integer within nth-child/nth-of-type.