Qual é a diferença entre: first-child e: first-of-type?

124

Eu não posso dizer a diferença entre element:first-childeelement:first-of-type

Por exemplo, digamos, você teve um div

div:first-child
→ Todos os <div>elementos que são os primeiros filhos de seus pais.

div:first-of-type
→ Todos os <div>elementos que são o primeiro <div>elemento de seu pai.

Parece exatamente a mesma coisa, mas funcionam de forma diferente.

Alguém poderia explicar?

BoltClock
fonte
O primeiro filho tem como alvo apenas o primeiro filho do pai, onde o primeiro do tipo tem como alvo o primeiro filho desse tipo (div ou um intervalo ou o que quer que você esteja tentando atingir)
Huangismo
O primeiro filho 'div' pode ter um irmão mais velho. first-of-type seleciona tal div, pois é o primeiro filho do tipo, first-child não selecionaria esse div porque não é o primeiro elemento filho.
n8bar

Respostas:

207

Um elemento pai pode ter um ou mais elementos filho:

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

Entre essas crianças, apenas uma delas pode ser a primeira. Isso é correspondido por :first-child:

<div class="parent">
  <div>Child</div> <!-- :first-child -->
  <div>Child</div>
  <div>Child</div>
  <div>Child</div>
</div>

A diferença entre :first-childe :first-of-typeé que :first-of-typecorresponderá ao primeiro elemento de seu tipo de elemento, que em HTML é representado por seu nome de tag, mesmo se esse elemento não for o primeiro filho do pai . Até agora, os elementos filhos que estamos vendo foram todos divs, mas tenha paciência comigo, vou chegar lá em breve.

Por enquanto, o inverso também é verdadeiro: qualquer :first-childum também é :first-of-typepor necessidade. Como o primeiro filho aqui também é o primeiro div, ele corresponderá a ambas as pseudo classes, bem como ao seletor 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>

Agora, se você mudar o tipo do primeiro filho divpara outra coisa, como h1, ainda será o primeiro filho, mas não será mais o primeiro divobviamente; em vez disso, ele se torna o primeiro (e único) h1. Se houver quaisquer outros divelementos seguindo este primeiro filho dentro do mesmo pai, o primeiro desses divelementos corresponderá div:first-of-type. No exemplo dado, o segundo filho se torna o primeiro divdepois que o primeiro filho é alterado para um 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>

Observe que :first-childé equivalente a :nth-child(1).

Isso também implica que, embora qualquer elemento possa ter apenas um único elemento filho correspondente :first-childpor vez, ele pode e terá tantos filhos correspondendo à :first-of-typepseudo classe quanto o número de tipos de filhos que ela possui. Em nosso exemplo, o seletor .parent > :first-of-type(com uma *qualificação implícita de :first-of-typepseudo) corresponderá a dois elementos, não apenas a um:

<div class="parent">
  <h1>Child</h1>   <!-- .parent > :first-of-type -->
  <div>Child</div> <!-- .parent > :first-of-type -->
  <div>Child</div>
  <div>Child</div>
</div>

O mesmo é verdadeiro para :last-childe :last-of-type: qualquer :last-childé por necessidade também :last-of-type, visto que absolutamente nenhum outro elemento o segue dentro de seu pai. Porém, como o último divé também o último filho, h1não pode ser o último filho, apesar de ser o último de seu tipo.

:nth-child()e :nth-of-type()funcionam de maneira muito semelhante em princípio quando usados ​​com um argumento inteiro arbitrário (como no :nth-child(1)exemplo mencionado acima), mas onde eles diferem é no número potencial de elementos correspondidos por :nth-of-type(). Isso é abordado em detalhes em Qual é a diferença entre p: n-ésimo filho (2) e p: n-ésimo-do-tipo (2)?

BoltClock
fonte
4
Eu finalmente entendi. Se eu quisesse o primeiro div em um elemento div, chamaria div: first-of-type, porque pode haver elementos não div acima dele. Foi um pouco confuso, mas agora entendo. Esta é uma postagem excelente e muito informativa. Obrigado e sua ajuda é muito apreciada.
1
Criei uma amostra com base nesta resposta: codepen.io/bigtinabang/pen/pmMPxO
Tina Chen
14

Criei um exemplo para demonstrar a diferença entre first-childe first-of-typeaqui.

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 o exemplo completo, visite https://jsfiddle.net/bwLvyf3k/1/

Wen
fonte
0

A diferença entre o tipo de primeiro filho e o primeiro filho pode ser entendida com o exemplo. Você precisa entender o exemplo a seguir criado por mim e ele realmente funciona, você pode colar os códigos em seu editor e entender o que são e como eles trabalham

Código # 1 para o primeiro do 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 serão estilizados e suas cores serão vermelhas. mesmo se colocarmos .p1 após o segundo div, ele será vermelho.

Código # 2 para o primeiro filho:

<!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:

se colocarmos o .p2 após o segundo div 2, ele não ficará vermelho, mas no primeiro caso estava funcionando.

Limpar tudo
fonte