Представьте список карточек или строк таблицы, где каждую вторую нужно подкрасить для удобства чтения, у последней — убрать разделительную линию, а самую первую — выделить. Можно навешать классы вручную на каждый элемент, но это утомительно и легко ошибиться: добавили карточку — и разметка «поехала». Структурные псевдоклассы решают это иначе: они выбирают элементы по их положению среди соседей, ничего не добавляя в HTML. Список остаётся чистым, а стили сами применяются к нужным элементам.
После этого урока вы сможете выбирать первый, последний и каждый n-й элемент, а также исключать элементы из выборки — и всё это одними селекторами, без лишних классов и без правок разметки при изменении числа элементов.
Что уже умеем / что добавим
На прошлом уроке вы научились стилизовать элементы по состоянию — наведению, фокусу, нажатию. Теперь научимся выбирать элементы по их месту в структуре: первый, последний, каждый чётный. В сквозном проекте мы наведём порядок в списке карточек услуг: сделаем «зебру» и уберём лишний отступ у последней карточки — без единого нового класса.
Что вы узнаете в рамках статьи
- Как выбрать первый и последний элемент через
:first-childи:last-child. - Как выбирать каждый n-й элемент с помощью
:nth-child(). - Как задавать чередование через
2n,oddиeven. - Как исключать элементы из выборки псевдоклассом
:not().
Ключевые термины
- Структурный псевдокласс — псевдокласс, выбирающий элемент по его положению среди соседей.
:first-child— первый дочерний элемент в своём родителе.:last-child— последний дочерний элемент в своём родителе.:nth-child(n)— элемент с определённым порядковым номером (или по формуле).:not(...)— элемент, который не подходит под указанный селектор.- Формула
an+b— выражение для:nth-child, задающее шаг и сдвиг выборки.
Первый и последний: :first-child и :last-child
Псевдоклассы :first-child и :last-child выбирают, соответственно, первый и последний элемент внутри его родителя. Частая задача — убрать разделительную границу или отступ у крайнего элемента:
<ul class="menu">
<li>Главная</li>
<li>Услуги</li>
<li>Контакты</li>
</ul>
.menu li {
border-bottom: 1px solid #ddd;
}
.menu li:last-child {
border-bottom: none;
}
Все пункты меню получат нижнюю границу, а :last-child уберёт её у последнего — список не будет заканчиваться лишней чертой. Красота в том, что при добавлении или удалении пунктов ничего править не нужно: «последним» всегда автоматически становится актуальный последний элемент. Аналогично :first-child удобен, чтобы, например, убрать верхний отступ у самого первого заголовка в блоке.
Каждый n-й: :nth-child()
:nth-child() — самый гибкий из структурных псевдоклассов. В скобках можно указать конкретный номер, ключевое слово или формулу. Простейший вариант — номер: :nth-child(2) выберет второй элемент. Ключевые слова odd и even выбирают нечётные и чётные элементы — так делают «зебру»:
.row:nth-child(even) {
background: #f5f7fa;
}
Каждая чётная строка получит светлый фон — классический приём для читаемости длинных списков и таблиц. Здесь тоже всё автоматически: добавили строки — чередование продолжится само. odd и even — это удобные псевдонимы: even эквивалентно формуле 2n, а odd — формуле 2n+1.
Формула an+b
Для более сложных выборок :nth-child() принимает формулу вида an+b, где браузер подставляет вместо n числа 0, 1, 2, 3 и так далее и выбирает элементы с получившимися номерами. Это звучит абстрактно, поэтому разберём на примерах:
/* Каждый третий элемент: 3, 6, 9, ... */
.item:nth-child(3n) { }
/* Каждый третий, начиная с первого: 1, 4, 7, ... */
.item:nth-child(3n+1) { }
В первом случае при n = 1, 2, 3 получаем номера 3, 6, 9 — каждый третий. Во втором 3n+1 даёт 1, 4, 7 — тоже с шагом три, но со сдвигом на один. Так можно, например, оформлять сетку по три в ряд, выделяя первый элемент каждого ряда. Формула кажется непривычной, но принцип один: a — это шаг чередования, b — сдвиг начала. Начните с odd/even, а к формулам переходите, когда нужен шаг больше двух.
Исключаем элементы: :not()
Псевдокласс :not() выбирает элементы, которые не подходят под указанный внутри селектор. Это удобно, когда правило нужно применить ко всем, кроме некоторых:
.btn:not(.btn-primary) {
background: #eee;
color: #333;
}
Здесь стиль получат все кнопки, кроме главной (.btn-primary) — не придётся заводить отдельный класс «второстепенная кнопка». :not() часто комбинируют с другими селекторами: например, li:not(:last-child) — «все пункты, кроме последнего» — удобная альтернатива для отступов между элементами. Внутрь :not() можно поместить класс, тег или даже другой псевдокласс, что делает его очень гибким инструментом для исключений.
Применяем в проекте
Наведём порядок в списке карточек услуг сайта компании. Сделаем «зебру», чтобы длинный список читался легче, и уберём нижний отступ у последней карточки, чтобы блок заканчивался ровно. Всё — без новых классов в разметке.
.card {
margin-bottom: 16px;
background: white;
}
.card:nth-child(even) {
background: #f5f7fa;
}
.card:last-child {
margin-bottom: 0;
}
Обновите страницу: чётные карточки получили лёгкий серый фон — список стало приятнее просматривать, а последняя карточка больше не создаёт лишнего отступа снизу. Мы не тронули HTML: добавляем и удаляем карточки свободно, а чередование и «ровный низ» подстраиваются сами. Это чистый и надёжный способ оформления повторяющихся элементов.
Частые ошибки
- Путаница
:nth-childи порядка.
Нумерация начинается с 1, а не с 0;:nth-child(1)— это первый элемент. :first-child, когда элемент не первый.
Псевдокласс сработает, только если элемент действительно первый среди всех соседей, а не первый своего типа; для выбора по типу есть:first-of-type.- Пробел внутри
:not().
Селектор пишут слитно:li:not(:last-child), а неli :not(...)— иначе смысл меняется на потомка. - Слишком сложные формулы.
Если можно обойтисьodd/even, не усложняйте формулой — код будет понятнее.
Итоги
Отличная работа — вы научились выбирать элементы по их месту в структуре! Теперь вы умеете обращаться к первому и последнему элементу через :first-child и :last-child, выбирать каждый n-й с помощью :nth-child() и формул an+b, делать «зебру» через odd/even и исключать элементы псевдоклассом :not(). В сквозном проекте вы навели порядок в списке карточек, не добавив ни одного класса, — и список теперь сам подстраивается под любое число элементов.
Так держать — ваш CSS становится всё выразительнее! В следующем уроке мы займёмся псевдоэлементами ::before и ::after: научимся добавлять декоративные детали — линии, значки, метки — прямо из стилей, без лишних тегов в разметке.