Как работают псевдоклассы в CSS. Подробное объяснение с примерами и диаграммами
17К открытий18К показов
Наверняка каждый, кто работал с CSS, не раз впадал в отчаяние. Например, когда пытался отцентрировать дочерний элемент по отношению к родительскому, что является весьма нетривиальной задачей. В этой статье мы рассмотрим ещё более сложную тему — псевдоклассы, один из видов селекторов.
Прим. перев. Псевдоклассы предназначены для изменения стиля существующих элементов страницы в зависимости от их динамического состояния, например, при работе со ссылками (:link
, :visited
, :hover
, :active
, :focus
).
В этой статье мы познакомимся с двумя типами псевдоклассов:
- селекторы
*-of-type
; - селекторы
*-child
.
Иногда сложно понять, что такое псевдоклассы и как они работают. Главная сложность состоит в том, что они представлены в абстрактном виде. Поэтому для упрощения восприятия использованы схемы с DOM-деревьями.
Разметка и DOM-дерево
Обратите внимание на HTML-код, представленный ниже. Он будет использоваться во всех примерах в этой статье.
А теперь давайте преобразуем этот код в нечто, понятное визуально и интуитивно — в DOM-дерево.
Давайте рассмотрим подробнее элемент body
. В нём расположено 3 дочерних элемента: main
и два элемента <a>
.
На схеме представлено отношение между body
и дочерними элементами.
Важен порядок, в котором дочерние элементы размещаются в дереве. В коде дочерние элементы располагаются сверху вниз, а в дереве — слева направо.
Теперь давайте посмотрим на div-контейнер с классом main
:
Контейнер с классом main
имеет 4 дочерних элемента: сначала два элемента <a>
, затем элемент ненумерованного списка ul
и снова <a>
-элемент.
Аналогичным образом спускаемся вниз по схеме согласно порядку вложенности элементов, отрисовывая полноценное дерево HTML-кода.
Внимательно изучите структуру DOM-дерева, чтобы легче воспринимать оставшуюся часть статьи.
Псевдокласс only-of-type (единственный из выбранного типа)
Для всех псевдоклассов действует один и тот же формат:
Выбираемый элемент служит для того, чтобы выбрать любой элемент из DOM. Обратите внимание на пример:
В приведённом выше фрагменте кода выбираемый элемент — тег <a>
, а его селектор — one-of-type
.
Данный пример можно изучить в работе на codepen.io. Уберите символы комментариев, чтобы посмотреть, как работает тот или иной селектор, а лучше продолжите чтение статьи, чтобы не запутаться.
Начнём с того, что выберем всё, что есть в DOM, а затем отфильтруем.
Обратите внимание, как был произведён выбор: в каждой секции (от 1 до 5) у элементов есть общий родительский элемент. Пример: родительский элемент для первой секции — body
, для второй секции — контейнер с классом main
, и т. д. Каждая секция соответствует уровню вложенности кода.
Так как в нашем случае выбираемым элементом являются элементы <a>
, то мы можем сделать следующее:
Мы выбрали все элементы <a>
в каждой секции и последовательно их пронумеровали слева направо. Не забывайте, что порядок очень важен.
Теперь мы завершаем часть работы, связанную с выбираемым элементом, и приступаем к фильтрации.
Only-of-type
проходит через все секции, выбирая только те элементы <a>
, которые являются единственными для своей секции.
Обратите внимание, что <a>
-элементы для первой и второй секций не были выбраны из-за того, что они не являются единственными для своих секций. Иначе говоря: одна секция — один элемент <a>
.
Псевдокласс first-of-type (первый из выбранного типа)
Давайте продолжим с того, на чём остановились — с выбираемого элемента (речь идёт об <a>
-теге).
Селектор first-of-type
выбирает каждый первый элемент <a>
в секции.
Код, который выполняет условия приведённой выше схемы:
Вы можете посмотреть как работает этот код в браузе на codepen.io.
Псевдокласс last-of-type (последний из выбранного типа)
Last-of-type
— полная противоположность псевдокласса first-of-type
. Этот селектор выбирает последние элементы <a>
во всех секциях.
Элемент <a>
— первый и последний для секций, в которых он представлен в единственном числе.
Псевдокласс nth-of-type (n-й из выбранного типа)
Теперь переходим к наиболее интересной части статьи. Рассмотрим простой CSS с элементами математики из школьной программы.
Давайте определим следующий стиль, чтобы посмотреть на селектор в действии:
Вместо nth
подставьте число из скобок в порядковой форме, чтобы прочитать правильно селектор.
Итак, давайте вернёмся к селектору. a:nth-of-type(1)
может читаться точно так же, как и a:first-of-type
. В данном случае эти селекторы работают одинаково: каждый из них выбирает только те элементы <a>
, которые являются первыми в своих секциях.
А теперь давайте попробуем кое-что другое:
Надеюсь, вы догадались, что произошло. Если нет, то объясняю: в этом случае ни один элемент <a>
не будет выбран, так как счёт начинается с 1, а не с 0. То же самое произойдёт, если вы напишете a:nth-of-type(5)
или a:nth-of-type(6/7/8)
вместо a:nth-of-type(0)
. Это легко можно объяснить: в DOM нет 5-го, 6-го, 7-го или 8-го элемента <a>
, поэтому в данном случае селектор ничего не выберет.
А если мы пойдём немного глубже и напишем следующее условие:
то селектор выберет каждый второй элемент <a>
в первой и во второй секциях.
Для полного понимания картины приведу ещё один пример:
В этом случае будет выбран третий (не перепутайте с a:last-of-type
) элемент <a>
во второй секции, так как эта секция — единственная, в которой есть три элемента <a>
.
Достаточно просто, не так ли? Но вставлять в скобки вы можете не только числа, но и формулы. Например, (a*n)+b
(то же самое, что и an + b
), где a и b — константы, а n —значение, которое больше или равно нулю. Не переживайте, если вам что-то непонятно, сейчас я всё объясню.
Для начала применим следующий стиль:
Формула, переданная в селектор выглядит следующим образом: (1 * n) + 0 [=n]
, где а = 1
, b = 0
, n
— переменная. Теперь давайте разберёмся, что идёт дальше. Значение n
последовательно вставляется в формулу, начиная с 0, после этого селектор делает выбор. Поэтому a:nth-of-type
можно представить следующим образом:
В соответствии с данными результатами и будет выбран элемент <a>
.
Давайте приведём ещё один пример:
При постепенном заполнении значений n
с нуля будут генерироваться следующие селекторы:
Помимо чисел и формул, генерирующих числа, вы можете также выбирать чётные или нечётные номера элементов. Even выбирает все чётные номера элемента в соответствующих секциях. Предположим, что у нас есть секция с 4-мя элементами <a>
. Из этой секции селектор выберет второй и четвёртый элементы <a>
. Аналогичным образом селектор работает с нечётными числами, только следует заменить even на odd — a:nth-of-type(odd) {style}
Псевдокласс nth-last-of-type (n-й с конца из выбранного типа)
Этот селектор работает точно так же, как и предыдущий, но с небольшим отличием:
Обратите внимание, что в каждой секции нумерация элементов <a>
идёт справа налево. Это и есть единственное отличие от предыдущего селектора. В :last-of-type
также можно использовать числа, формулы и выбор по чётным и нечётным номерам элементов. Главное запомнить, что для этого селектора работает обратный отбор, его следует читать справа налево. Иначе говоря, последний элемент превращается в первый, предпоследний превращается во второй и т. д.
На этом часть статьи о селекторах *-of-type
подходит к концу. Надеюсь, что вам понравилось. Мы проделали большой путь от only-of-type
до nth-last-of-type
, углубившись в first-of-type
, last-of-type
и nth-of-type
. Если где-то в середине вы что-то не до конца поняли, то предлагаю вам поэкспериментировать в codepen и перечитать эту часть.
Настало время перейти к новой категории псевдоклассов — *-child
. В этой части статьи мы рассмотрим и попытаемся понять, как работает эта категория селекторов. После того, как вы изучили предыдущие селекторы, эта категория псевдоклассов не покажется вам трудной. Давайте начнём!
Псевдокласс only-child (единственный из выбранного типа дочернего элемента)
Примените следующий стиль к HTML-коду, который дан в самом начале .
Как вы видите, селектор выбрал два <a>
-элемента, каждый из которых вложен в элемент «список» li
. Почему так и как это работает: only child дословно переводится как «единственный ребёнок / единственный дочерний элемент», поэтому селектор выбирает только те <a>
-элементы, у которых родительский элемент имеет только один дочерний элемент —<a>
. В нашем случае каждый li
имеет по одному родительскому и по одному дочернему элементу, поэтому они и были выбраны.
Почему не выбран <a>
-элемент, единственный дочерний элемент <a>
ненумерованного списка ul
? Ответ прост: несмотря на то, что он является единственным дочерним <a>
-элементом, у него есть ещё два соседа, не являющихся элементами <a>
, для которых ul
является родительским. Получается три дочерних элемента, что, разумеется, не попадает под наше правило: один родительский элемент — один дочерний.
Псевдокласс first-child (первый дочерний элемент)
Примените следующий стиль:
Селектор first-child
выбирает все первые дочерние элементы <a>
своих родителей. Следует помнить, что он выбирает только первые дочерние <a>
-элементы. Это означает, что элемент <a>
должен занимать первую позицию в своей секции, а не быть первым после какого-либо другого дочернего элемента.
Если вы не поняли, почему первый дочерний <a>
-элемент в body
не был выбран, то сейчас объясню. Дело в том, что он является первым только среди дочерних <a>
-элементов в этой секции. Среди всех дочерних элементов он — второй, так как первый — это контейнер с классом main
.
Псевдокласс last-child (последний дочерний элемент)
Думаю, что после всего материала, который мы изучили, вы примерно понимаете, как работает этот селектор. Если нет — объясняю: last-child
выбирает последний элемент <a>
в каждой секции. Правило прежнее: <a>
-элемент должен быть именно первым в списке всех дочерних элементов, иначе он не будет выбран.
Обратите внимание на схему после кода.
Псевдокласс nth-child (n-й дочерний элемент)
Надеюсь, вы усвоили небольшой урок математики в первой части статьи. Потому что сейчас это произойдёт снова, но с небольшими изменениями.
Обратите внимание на следующий пример:
Всё работает так же, как и с селектором nth-of-type
.
Чтобы начать использовать nth-child
, нужно повторить все те действия, которые мы произвели с селектором nth-of-type
— поместить в скобки любое число. В примере выше селектор сработает точно так же, как и first-child
— выберет все первые элементы <a>
в секциях.
Итак, давайте перейдём к новому примеру:
Постепенно добавляем значения n
в формулу начиная с 0, и это даёт нам понять, что селектор сверху во многом схож тем, что ниже.
Если селектор получает числа, выходящие за пределы секторов (как -1, 5, 6), он просто их игнорирует.
На схеме ниже показано действие селектора a:nth-child(2n-1)
:
На сайте CSS Tricks вы сможете найти очень полезную и исчерпывающую статью о селекторе :nth-child
.
А пока что давайте перейдём к последнему селектору в нашем руководстве.
Псевдокласс nth-last-child (n-й дочерний элемент с конца)
Этот селектор работает точно так же, как и :nth-child
, за исключением одной тонкости: он видит и читает дерево DOM в обратном направлении — справа налево.
Дочерние элементы в каждой секции для этого селектора выстраиваются в ряд справа налево.
Обратите внимание на то, как расположены и выбраны дочерние элементы на схеме:
Как видите, всё довольно просто — выбор элемента происходит с конца.
Заключение
На этом наше знакомство с псевдоклассами окончено. Но вы всегда можете найти полезный материал по CSS у нас на сайте. Желаем вам удачи в освоении CSS!
17К открытий18К показов