Селекторы :nth-child, :last-of-type, :not, :empty и им подобные. Надо разбираться…

Это расширенное руководство по псевдоклассам CSS для позиционного выбора элементов охватывает все основные селекторы семейства nth, а также дополнительные псевдоклассы для точного выбора элементов на веб-странице.

Основные псевдоклассы для позиционного выбора

:nth-child() — выбор по позиции среди всех соседних элементов

Селектор :nth-child() выбирает элементы по их порядковому номеру, учитывая все элементы на одном уровне, независимо от их типа.

Синтаксис: :nth-child(n)

Ключевая особенность: Считает все элементы на уровне, не важно какого они типа.

Основные варианты использования:

CSS
/* Конкретный элемент */
li:nth-child(4) { color: red; }

/* Четные элементы */
p:nth-child(even) { background: lightgray; }
p:nth-child(2n) { background: lightgray; } /* аналогично */

/* Нечетные элементы */
div:nth-child(odd) { border: 1px solid blue; }
div:nth-child(2n+1) { border: 1px solid blue; } /* аналогично */

/* Каждый третий элемент */
span:nth-child(3n) { font-weight: bold; }

/* Первые 5 элементов */
li:nth-child(-n+5) { text-decoration: underline; }

/* Начиная с 3-го элемента */
div:nth-child(n+3) { margin-top: 10px; }

Математические выражения в :nth-child():

  • an+b — где a и b целые числа, n — счетчик от 0
  • 3n+2 выберет элементы 2, 5, 8, 11, 14…
  • 4n+1 выберет элементы 1, 5, 9, 13…
  • -n+3 выберет первые 3 элемента

:nth-of-type() — выбор по позиции среди элементов одного типа

Селектор :nth-of-type() выбирает элементы по порядковому номеру, но учитывает только элементы указанного типа.

Синтаксис: :nth-of-type(n)

Ключевая особенность: Считает только элементы того же типа.

CSS
/* Второй параграф (считая только <p>) */
p:nth-of-type(2) { font-size: 18px; }

/* Каждое четное изображение */
img:nth-of-type(even) { border-radius: 10px; }

/* Каждый третий заголовок h2 */
h2:nth-of-type(3n) { color: purple; }

Разница между :nth-child() и :nth-of-type():

HTML
<div>
  <h1>Заголовок</h1>
  <p>Первый параграф</p><!-- p:nth-child(2), p:nth-of-type(1) -->
  <p>Второй параграф</p><!-- p:nth-child(3), p:nth-of-type(2) -->
</div>

:nth-last-child() — выбор с конца среди всех элементов

Работает как :nth-child(), но отсчет ведется с последнего элемента.

CSS
/* Предпоследний элемент */
li:nth-last-child(2) { font-style: italic; }

/* Последние 3 элемента */
div:nth-last-child(-n+3) { background: yellow; }

/* Четные элементы с конца */
tr:nth-last-child(even) { background: #f0f0f0; }

:nth-last-of-type() — выбор с конца среди элементов одного типа

Аналог :nth-of-type(), но отсчет с конца и только среди элементов того же типа.

CSS
/* Последний параграф */
p:nth-last-of-type(1) { margin-bottom: 0; }

/* Второй span с конца */
span:nth-last-of-type(2) { text-decoration: underline; }

/* Каждый третий элемент с конца */
p:nth-last-of-type(3n) { background: red; }

Селекторы для выбора первых и последних элементов

:first-child и :last-child

Выбирают первый и последний элемент среди всех соседних элементов.

CSS
/* Первый элемент любого типа */
p:first-child { margin-top: 0; }

/* Последний элемент любого типа */
li:last-child { border-bottom: none; }

Важно: Элемент должен действительно быть первым/последним среди всех элементов, а не только своего типа.

:first-of-type и :last-of-type

Выбирают первый и последний элемент конкретного типа.

CSS
/* Первый заголовок h2 в контексте */
h2:first-of-type { color: blue; }

/* Последний параграф */
p:last-of-type { margin-bottom: 20px; }

/* Первое изображение */
img:first-of-type { border: 3px solid gold; }

Селекторы для единственных элементов

:only-child

Выбирает элемент, который является единственным дочерним элементом своего родителя.

CSS
/* span, который единственный в родителе */
span:only-child { 
  font-weight: bold; 
  color: red; 
}

/* Единственный элемент списка */
li:only-child { 
  list-style: none; 
  text-align: center; 
}

Эквивалентно записи: :first-child:last-child

:only-of-type

Выбирает элемент, который является единственным элементом своего типа среди соседей.

CSS
/* Единственный заголовок h1 */
h1:only-of-type { text-align: center; }

/* Единственная таблица в контейнере */
table:only-of-type { width: 100%; }

Специальные псевдоклассы

:empty — выбор пустых элементов

Выбирает элементы, которые не содержат текста или дочерних элементов.

CSS
/* Скрыть пустые div */
div:empty { display: none; }

/* Стилизация пустых параграфов */
p:empty { 
  height: 20px; 
  background: #f0f0f0; 
  border: 1px dashed #ccc; 
}

/* Скрыть пустые элементы реакций */
.reactions:empty { display: none; }

Важные нюансы :empty:

  • Пробелы и переносы строк считаются содержимым
  • HTML-комментарии НЕ считаются содержимым
  • Псевдоэлементы НЕ считаются содержимым
HTML
<div></div>                    <!-- Пустой -->
<div> </div>                   <!-- НЕ пустой (пробел) -->
<div><!-- комментарий --></div>  <!-- Пустой -->
<div><br></div>                <!-- НЕ пустой (дочерний элемент) -->

:not() — отрицающий селектор

Исключает из выборки элементы, соответствующие указанному селектору.

CSS
/* Все div, кроме с классом special */
div:not(.special) { opacity: 0.8; }

/* Все активные поля ввода */
input:not(:disabled) { border: 2px solid green; }

/* Все элементы списка кроме последнего */
li:not(:last-child) { margin-bottom: 10px; }

/* Все кнопки кроме primary и danger */
button:not(.primary):not(.danger) { opacity: 0.5; }

Современный синтаксис CSS4 (ограниченная поддержка):

CSS
/* Список селекторов через запятую */
button:not(.primary, .danger) { opacity: 0.5; }

Комбинирование селекторов

Выбор диапазона элементов

Для выбора элементов в определенном диапазоне используйте комбинацию селекторов:

CSS
/* Элементы с 4 по 8 включительно */
li:nth-child(n+4):nth-child(-n+8) { 
  background: lightblue; 
}

/* Все элементы кроме первых трех */
p:nth-child(n+4) { margin-left: 20px; }

/* Первые 5 элементов */
div:nth-child(-n+5) { border-top: 1px solid black; }

Условные селекторы по количеству

Выбор элементов в зависимости от общего количества:

CSS
/* Первый элемент, только если всего элементов 6 */
li:nth-last-child(6):first-child { color: tomato; }

/* Все элементы, только если их 6 или больше */
li:nth-last-child(n+6), 
li:nth-last-child(n+6) ~ li { color: green; }

/* Все элементы, только если их 6 или меньше */
li:nth-last-child(-n+6):first-child, 
li:nth-last-child(-n+6):first-child ~ li { color: blue; }

Практические примеры

Стилизация таблиц

CSS
/* Полосатая таблица */
tr:nth-child(even) { background: #f9f9f9; }
tr:nth-child(odd) { background: white; }

/* Первая строка заголовка */
thead tr:first-child { 
  font-weight: bold; 
  background: #333; 
  color: white; 
}

/* Последняя ячейка в строке */
td:last-child { text-align: right; }

Навигационные меню

CSS
/* Все пункты меню кроме последнего */
.menu li:not(:last-child) { border-right: 1px solid #ddd; }

/* Первый пункт меню */
.menu li:first-child a { padding-left: 0; }

/* Активный пункт меню, но не последний */
.menu li.active:not(:last-child) { 
  border-right-color: #007acc; 
}

Формы

CSS
/* Все поля ввода кроме отключенных */
input:not(:disabled):focus { 
  border-color: blue; 
  box-shadow: 0 0 5px rgba(0,0,255,0.3); 
}

/* Каждое второе поле для создания "зебры" */
.form-field:nth-child(even) { background: #f8f8f8; }

/* Последнее поле в форме */
.form-field:last-child { margin-bottom: 0; }

Галереи изображений

CSS
/* Каждое третье изображение в ряд */
.gallery img:nth-child(3n) { margin-right: 0; }

/* Первое изображение в галерее */
.gallery img:first-of-type { 
  width: 100%; 
  height: 300px; 
  object-fit: cover; 
}

/* Пустые контейнеры изображений */
.image-placeholder:empty { 
  background: #ddd; 
  height: 200px; 
  display: flex; 
  align-items: center; 
  justify-content: center; 
}

Лучшие практики и советы

1. Производительность

  • Избегайте слишком сложных выражений
  • :nth-child() может быть медленнее :first-child или :last-child
  • Используйте классы для часто повторяющихся паттернов

2. Читаемость кода

CSS
/* Хорошо */
.article p:first-of-type { font-size: 18px; }

/* Избегайте слишком сложных селекторов */
.content div:nth-child(3n+2):not(.special):first-of-type { ... }

3. Совместимость

  • Большинство селекторов поддерживается всеми современными браузерами
  • :not() с несколькими селекторами (CSS4) имеет ограниченную поддержку

4. Отладка

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

CSS
/* Временно подсветить выбранные элементы */
li:nth-child(3n+1) { 
  outline: 2px solid red !important; 
}

Эти CSS-селекторы предоставляют мощные инструменты для точного выбора элементов без необходимости добавления дополнительных классов в HTML. Правильное использование этих псевдоклассов позволяет создавать более чистый и гибкий код стилизации.