A main container can contain multiple smaller containers:
<div class="main">
<div>Child</div>
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
Out of these children, only one can be considered the first. This is identified by :first-child
:
<div class="main">
<div>Child</div> <!-- :first-child -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
The distinction between :first-child
and :first-of-type
lies in the fact that :first-of-type
matches the first element of its type within the parent, even if it's not the initial child of the container. At this moment, all child elements examined are div
, but we'll explore other types shortly.
Conversely, any element marked as :first-child
is also inherently
:first-of-type</code. Because the first child here is a <code>div
, it will match both pseudo-classes as well as the tag selector
div
:
<div class="main">
<div>Child</div> <!-- div:first-child, div:first-of-type -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
If you change the type of the first child from div
to another like h1
, it remains the primary child but no longer the first div
. Instead, it now becomes the sole h1
. Following this scenario, if there are more div
elements after the first child, the next div
would then meet the criteria for div:first-of-type
. In the provided example, the second child becomes the initial div
following the conversion of the first child to an h1
:
<div class="main">
<h1>Child</h1> <!-- h1:first-child, h1:first-of-type -->
<div>Child</div> <!-- div:nth-child(2), div:first-of-type -->
<div>Child</div>
<div>Child</div>
</div>
It should be noted that :first-child
is identical to :nth-child(1)
.
This indicates that though an element may have just one child matching :first-child
at a time, it can possess several children meeting the :first-of-type
criteria based on their types. In our instance, the selection .main > :first-of-type
(implicitly qualifying :first-of-type
) will find two elements rather than one:
<div class="main">
<h1>Child</h1> <!-- .main > :first-of-type -->
<div>Child</div> <!-- .main > :first-of-type -->
<div>Child</div>
<div>Child</div>
</div>
The same concept applies to :last-child
and :last-of-type
: any :last-child
is essentially :last-of-type
because there are no additional elements following it in the parent. However, since the final div
is also the last child, the h1
cannot hold that position despite being the ultimate element of its kind.
:nth-child()
and :nth-of-type()
behave similarly when using an integer argument (like :nth-child(1)
mentioned earlier) with their disparity lying in the number of matches found by :nth-of-type()
. This topic is explored further in What is the difference between p:nth-child(2) and p:nth-of-type(2)?