В чем разница между: first-child и: first-of-type?

Я не могу сказать разницу между element:first-child и element:first-of-type

Например, у вас был div

div:first-child
→ Все элементы <div>, которые являются первым потомком родителя.

div:first-of-type
→ Все элементы <div>, которые являются первым элементом <div> их родителя.

Это похоже на то же самое, но они работают по-другому.

Может кто-нибудь объяснит?

Ответ 1

Родительский элемент может иметь один или несколько дочерних элементов:

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

Среди этих детей только один из них может быть первым. Это соответствует :first-child:

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

Разница между :first-child и :first-of-type заключается в том, что :first-of-type будет соответствовать первому элементу своего типа элемента, который в HTML представлен его именем тега, даже если этот элемент не является первым дочерним элементом родительского элемента, До сих пор дочерние элементы, на которые мы смотрим, были div s, но неся со мной, я немного доберусь до этого.

В этом случае верно и обратное: любой :first-child по необходимости также :first-of-type. Поскольку первый ребенок здесь также является первым div, он будет соответствовать как псевдоклассам, так и селектору типа div:

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

Теперь, если вы измените тип первого дочернего элемента из div на что-то еще, например h1, он все равно будет первым потомком, но он уже не будет первым div; вместо этого он становится первым (и только) h1. Если есть другие элементы div, следующие за этим первым дочерним элементом внутри одного и того же родителя, первый из этих элементов div будет соответствовать div:first-of-type. В данном примере второй ребенок становится первым div после того, как первый ребенок будет изменен на 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>

Обратите внимание, что :first-child эквивалентно :nth-child(1).

Это также подразумевает, что, хотя любой элемент может иметь только один дочерний элемент, соответствующий :first-child за раз, он может и будет иметь столько же детей, которые соответствуют псевдоклассу :first-of-type, как число типов детей, которые он имеет, В нашем примере селектор .parent > :first-of-type (с неявным *, квалифицирующим псевдоним :first-of-type) будет соответствовать двум элементам, а не только одному:

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

То же самое справедливо для :last-child и :last-of-type: any :last-child по необходимости также :last-of-type, так как абсолютно никакой другой элемент не следует за его родителем. Тем не менее, поскольку последний div также является последним дочерним, h1 не может быть последним дочерним элементом, несмотря на то, что он последний из его типов.

Ответ 2

Я создал пример, чтобы продемонстрировать разницу между first-child и first-of-type здесь.

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;
}

Чтобы увидеть полный пример, посетите https://jsfiddle.net/bwLvyf3k/1/