¿Cuál es la diferencia entre: first-child y: first-of-type?

124

No puedo distinguir la diferencia entre element:first-childyelement:first-of-type

Por ejemplo, digamos que tenía un div

div:first-child
→ Todos los <div>elementos que son el primer hijo de su padre.

div:first-of-type
→ Todos los <div>elementos que son el primer <div>elemento de su padre.

Esto parece exactamente lo mismo, pero funcionan de manera diferente.

¿Podría alguien explicarme?

BoltClock
fuente
El primer hijo solo se dirige al primer hijo del padre, donde el primero del tipo apunta al primer hijo de ese tipo (div o un intervalo o lo que sea que está tratando de apuntar)
Huangism
El primer hijo 'div' podría tener un hermano mayor. first-of-type selecciona tal div ya que es el primer hijo del tipo, first-child no seleccionaría ese div porque no es el primer elemento hijo.
n8bar

Respuestas:

207

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-childy :first-of-typees que :first-of-typecoincidirá 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 divs, pero tengan paciencia conmigo, llegaré a eso en un momento.

Por ahora, lo contrario también es cierto: cualquiera :first-childes también :first-of-typepor 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 diva otro, por ejemplo h1, seguirá siendo el primer hijo, pero divobviamente ya no será el primero ; en cambio, se convierte en el primero (y único) h1. Si hay otros divelementos que siguen a este primer hijo dentro del mismo padre, el primero de esos divelementos coincidirá div:first-of-type. En el ejemplo dado, el segundo hijo se convierte en el primero divdespué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-childes equivalente a :nth-child(1).

Esto también implica que, si bien cualquier elemento puede tener un único elemento hijo que coincida :first-childa la vez, puede tener tantos hijos que coincidan con la :first-of-typepseudoclase 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-typepseudo) 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-childy :last-of-type: any :last-childes necesariamente también :last-of-type, ya que ningún otro elemento lo sigue dentro de su padre. Sin embargo, como el último dives también el último hijo, h1no 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)?

BoltClock
fuente
4
Finalmente lo entiendo. Si quisiera el primer div debajo de un elemento div, llamaría div: first-of-type, porque podría haber elementos no div encima de él. Fue un poco confuso, pero ahora lo entiendo. Esta es una publicación excelente y muy informativa. Gracias y su ayuda es muy apreciada.
1
Creé
Tina Chen
14

He creado un ejemplo para demostrar la diferencia entre first-childy first-of-typeaquí.

HTML

<div class="parent">
  <p>Child</p>
  <div>Child</div>
  <div>Child</div>
  <div>Child</div>
</div> 

CSS

.parent :first-child {
  color: red;
}

.parent :first-of-type {
  background: yellow;
}

.parent p:first-child {
  text-decoration: line-through;
}

// Does not work
.parent div:first-child {
  font-size: 20px;
}
// Use this instead
.parent div:first-of-type {
  text-decoration: underline;
}
// This is second child regardless of its type
.parent div:nth-child(2) {
  border: 1px black solid;
}

Para ver el ejemplo completo, visite https://jsfiddle.net/bwLvyf3k/1/

Wen
fuente
0

La diferencia entre el tipo de primer hijo y el primer hijo se puede entender con el ejemplo. Necesita comprender el siguiente ejemplo creado por mí y realmente funciona, puede pegar los códigos en su editor, comprenderá qué son y cómo trabajan

Código # 1 para el primero de tipo:

<!DOCTYPE html>
<html>
<head>
<title>clear everything</title>
<style>
p:first-of-type{
color:red;
}
</style>
<head>
<body>
<p class="p1">some text</p>
<div>
<p class="p2">some text</p>
<div>
<p class="p3">some text</p>
</div>
<p class="p4">some text</p>
</div>
<p class="p5">some text</p>
</body>
</html>

resultado

.p1, .p2, .p3 tendrán estilo y su color será rojo. Incluso si ponemos .p1 después del segundo div, será rojo.

Código # 2 para el primer hijo:

<!DOCTYPE html>
<html>
<head>
<title>clear everything</title>
<style>
p:first-child{
color:red;
}
</style>
<head>
<body>
<p class="p1">some text</p>
<div>
<p class="p2">some text</p>
<div>
<p class="p3">some text</p>
</div>
<p class="p4">some text</p>
</div>
<p class="p5">some text</p>
</body>
</html>

resultado:

si ponemos el .p2 después del segundo div 2 no será rojo sin embargo en el primer caso estaba funcionando.

Limpiar todo
fuente