nth-child vs nth-of-type

Автор: Ire Aderinokun    Источник: bitsofco.de
04.02.2017
569
0
img

Селекторы nth-child() и nth-of-type() – это «структурные» псевдо-классы, которые позволяют выбрать элементы, основываясь на их позиции в дереве, чего нельзя сделать с помощью других селекторов. В случае с nth-child() и nth-of-type() учитывается позиция элемента относительно родителя и соседей. Не смотря на то, что эти два псевдо-класса очень похожи, работают они совершенно по-разному.

Как работает nth-child()

nth-child() используется для выбора элемента, основываясь на номере, который является порядковым номером элемента среди его соседей. Если точнее, то номер представляет собой число соседей идущих до выбранного элемента (минус 1).

Это число выражается как функция an+b, где «n» – это индекс, а «а» и «b» - любые целые числа. Например, чтобы выбрать все элементы, мы можем написать какой-либо из следующих вариантов:

:nth-child(1n+0) { /* styles */ }
:nth-child(n+0) { /* styles */ }
:nth-child(1n) { /* styles */ }

Также мы можем просто подставить целое число, например, :nth-child(1) или использовать ключевые слова, odd или even. Эти ключевые слова – альтернатива функциям для выбора каждого нечетного или четного элемента.

:nth-child(odd) { /* styles for odd elements */ }
:nth-child(2n+1) { /* styles for odd elements */ }

:nth-child(even) { /* styles for even elements */ }
:nth-child(2n+0) { /* styles for even elements */ }

Если использовать :nth-child() сам по себе, то спрогнозировать, какой элемент будет выбран достаточно просто. К примеру, используя эту разметку –

<div class="example">  
    <p>This is a <em>paragraph</em>.</p>
    <p>This is a <em>paragraph</em>.</p>
    <p>This is a <em>paragraph</em>.</p>
    <div>This is a <em>divider</em>.</div>
    <div>This is a <em>divider</em>.</div> <!-- Element to select -->
    <p>This is a <em>paragraph</em>.</p>
    <p>This is a <em>paragraph</em>.</p>
    <div>This is a <em>divider</em>.</div>
    <p>This is a <em>paragraph</em>.</p>
    <div>This is a <em>divider</em>.</div>
</div>  

Если мы хотим выбрать 5й элемент, div, мы можем просто написать следующее –

.example :nth-child(5) { background: #ffdb3a; }

Однако, можно получить неожиданный результат, если есть элементы разного типа и нужно комбинировать :nth-child() с тегом или классом. К примеру, чтобы снова выбрать тот же div, скорее всего мы напишем следующее –

.example div:nth-child(2) { background: #ffdb3a; } /* не правильно */

Причина, по которой это не работает в том, что элемента, который бы соответствовал такому селектору, не существует. Используя этот селектор, браузер выполняет следующие команды:

  • Выбрать все дочерние элементы .example.
  • Найти второй элемент в списке, независимо от типа.
  • Проверить является ли этот элемент div’ом.

Поскольку второй элемент в дереве – это параграф, а не div, ничего не выбирается. Если мы хотим выбрать второй div, то нужно использовать псевдо-класс nth-of-type().

Как работает nth-of-type()

Псевдо-класс nth-of-type() , так же как и nth-child(), используется для выбора элемента по номера. Однако, этот номер является порядковым номером элемента среди соседей такого же типа.

Этот номер тоже может быть выражен как функция, или используя ключевые слова even или odd. Используя пример выше, мы можем выбрать все нечетные параграфы, написал следующее –

.example p:nth-of-type(odd) { background: #ffdb3a; }

Когда мы используем этот селектор, браузер выполяет следующие команды:

  • Выбрать все дочерние элементы .example типа «p».
  • Создать новый список из этих элементов.
  • Выбрать нечетные из этого списка.

Учитывая это, чтобы выбрать второй div, 5й дочерний элемент .example, нужно написать следующее –

.example div:nth-of-type(2) { /* styles */ } 

Другие "nth" псевдо-классы

Кроме nth-child() и nth-of-type() есть еще много других структурных псевдо-классов, которые мы можем использовать для выбора элемента по его номеру среди соседей. Так же как и nth-child() и nth-of-type() они делятся на две группы – те, что не зависят от типа, как nth-child(), и те, что зависят, как nth-of-type().

Подсчет с конца - nth-last-child() vs nth-last-of-type()

Эти псевдо-классы работают также как и nth-child() and nth-of-type(), но они начинают подсчет с последнего элемента, вместо первого.

.example :nth-last-child(1) { background: #a6cae7; } 
.example p:nth-last-of-type(1) { background: #ffdb3a; } 

Первый элемент - first-child() vs first-of-type()

Псевдо-классы first-child() и first-of-type() выбирают первый элемент. Их можно рассматривать как аналоги nth-child() и nth-of-type(), но с подставленным значением 1.

.example :first-child() { /* styles */ }
.example :nth-child(1) { /* styles */ } /* same as above */

.example :first-of-type() { /* styles */ }
.example :nth-of-type(1) { /* styles */ } /* same as above */

Последний элемент - last-child() vs last-of-type()

Эти псевдо-классы противоположны first-child() и first-of-type(). Их можно рассматривать как аналоги псевдо-классам nth-last-child() и nth-last-of-type() с подставленной единичкой.

.example :last-child() { /* styles */ }
.example :nth-last-child(1) { /* styles */ } /* same as above */

.example :last-of-type() { /* styles */ }
.example :nth-last-of-type(1) { /* styles */ } /* same as above */

Один элемент - only-child() vs only-of-type()

И наконец, эти псевдо-классы выберут элемент, если он единственный дочерний у этого родителя. Для only-child() элемент должен быть единственным дочерним элементом не смотря на тип. А для only-of-type() элемент должен быть единственным дочерним элементом конкретного типа.

.example :only-child() { /* styles */ }
.example p:only-of-type() { /* styles */ }

ПОХОЖИЕ СТАТЬИ: