Un élément parent peut avoir un ou plusieurs éléments enfants:
<div class="parent">
<div>Child</div>
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
Parmi ces enfants, un seul d'entre eux peut être le premier. Ceci correspond à :first-child:
<div class="parent">
<div>Child</div> <!-- :first-child -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
La différence entre :first-childet :first-of-typeest qu'il :first-of-typecorrespondra au premier élément de son type d'élément, qui en HTML est représenté par son nom de balise, même si cet élément n'est pas le premier enfant du parent . Jusqu'à présent, les éléments enfants que nous examinons ont tous été des divs, mais soyez indulgents, j'y reviendrai dans un instant.
Pour l'instant, l'inverse est également vrai: tout :first-childest également :first-of-typepar nécessité. Puisque le premier enfant ici est également le premier div, il correspondra aux deux pseudo-classes, ainsi qu'au sélecteur de type div:
<div class="parent">
<div>Child</div> <!-- div:first-child, div:first-of-type -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
Maintenant, si vous changez le type du premier enfant de divà quelque chose d'autre, comme h1, ce sera toujours le premier enfant, mais ce ne sera plus le premier divévidemment; au lieu de cela, il devient le premier (et le seul) h1. S'il y a d'autres divéléments suivant ce premier enfant dans le même parent, le premier de ces divéléments correspondra alors div:first-of-type. Dans l'exemple donné, le deuxième enfant devient le premier divaprès que le premier enfant est changé en h1:
<div class="parent">
<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>
Notez que cela :first-childéquivaut à :nth-child(1).
Cela implique également que bien qu'un élément ne puisse avoir qu'un seul élément enfant correspondant :first-childà la fois, il peut et aura autant d'enfants correspondant à la :first-of-typepseudo-classe que le nombre de types d'enfants qu'il possède. Dans notre exemple, le sélecteur .parent > :first-of-type(avec une *qualification implicite du :first-of-typepseudo) correspondra à deux éléments, pas seulement un:
<div class="parent">
<h1>Child</h1> <!-- .parent > :first-of-type -->
<div>Child</div> <!-- .parent > :first-of-type -->
<div>Child</div>
<div>Child</div>
</div>
Il en va de même pour :last-childand :last-of-type: any l' :last-childest aussi par nécessité :last-of-type, puisque absolument aucun autre élément ne le suit dans son parent. Pourtant, comme le dernier divest aussi le dernier enfant, le h1ne peut pas être le dernier, bien qu'il soit le dernier de son type.
:nth-child()et :nth-of-type()fonctionnent de manière très similaire en principe lorsqu'ils sont utilisés avec un argument entier arbitraire (comme dans l' :nth-child(1)exemple mentionné ci-dessus), mais là où ils diffèrent, c'est dans le nombre potentiel d'éléments correspondant à :nth-of-type(). Ceci est traité en détail dans Quelle est la différence entre p: nth-child (2) et p: nth-of-type (2)?