Un elemento principal puede tener uno o más elementos secundarios:
<div class="parent">
<div>Child</div>
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
Entre estos niños, solo uno de ellos puede ser el primero. Esto se corresponde con :first-child
:
<div class="parent">
<div>Child</div> <!-- :first-child -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
La diferencia entre :first-child
y :first-of-type
es que :first-of-type
coincidirá con el primer elemento de su tipo de elemento, que en HTML está representado por su nombre de etiqueta, incluso si ese elemento no es el primer elemento secundario del padre . Hasta ahora, los elementos secundarios que estamos viendo han sido todos div
s, pero tengan paciencia conmigo, llegaré a eso en un momento.
Por ahora, lo contrario también es cierto: cualquiera :first-child
es también :first-of-type
por necesidad. Dado que el primer hijo aquí también es el primero div
, coincidirá con ambas pseudoclases, así como con el selector de tipo div
:
<div class="parent">
<div>Child</div> <!-- div:first-child, div:first-of-type -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>
Ahora, si cambia el tipo del primer hijo de div
a otro, por ejemplo h1
, seguirá siendo el primer hijo, pero div
obviamente ya no será el primero ; en cambio, se convierte en el primero (y único) h1
. Si hay otros div
elementos que siguen a este primer hijo dentro del mismo padre, el primero de esos div
elementos coincidirá div:first-of-type
. En el ejemplo dado, el segundo hijo se convierte en el primero div
después de que el primer hijo se cambia a 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>
Tenga en cuenta que :first-child
es equivalente a :nth-child(1)
.
Esto también implica que, si bien cualquier elemento puede tener un único elemento hijo que coincida :first-child
a la vez, puede tener tantos hijos que coincidan con la :first-of-type
pseudoclase como el número de tipos de hijos que tenga. En nuestro ejemplo, el selector .parent > :first-of-type
(con una *
calificación implícita del :first-of-type
pseudo) coincidirá con dos elementos, no solo con uno:
<div class="parent">
<h1>Child</h1> <!-- .parent > :first-of-type -->
<div>Child</div> <!-- .parent > :first-of-type -->
<div>Child</div>
<div>Child</div>
</div>
Lo mismo es cierto para :last-child
y :last-of-type
: any :last-child
es necesariamente también :last-of-type
, ya que ningún otro elemento lo sigue dentro de su padre. Sin embargo, como el último div
es también el último hijo, h1
no puede ser el último hijo, a pesar de ser el último de su tipo.
:nth-child()
y :nth-of-type()
funcionan de manera muy similar en principio cuando se usan con un argumento entero arbitrario (como en el :nth-child(1)
ejemplo mencionado anteriormente), pero donde difieren es en el número potencial de elementos emparejados por :nth-of-type()
. Esto se cubre en detalle en ¿Cuál es la diferencia entre p: nth-child (2) y p: nth-of-type (2)?