Псевдоклассы

Подкаст CSS - 015: Псевдоклассы

Допустим, у вас есть форма регистрации для отправки электронного письма, и вы хотите, чтобы поле формы отображалось красной рамкой, если оно содержит недействительный адрес электронной почты. Как это сделать? Можно использовать CSS-псевдокласс :invalid , один из множества псевдоклассов, предоставляемых браузером.

Псевдокласс позволяет применять стили на основе изменений состояния и внешних факторов. Это означает, что ваш дизайн может реагировать на пользовательский ввод, например, на неверный адрес электронной почты. Эти вопросы рассматриваются в модуле «Селекторы» , и этот модуль расскажет о них подробнее.

В отличие от псевдоэлементов, о которых вы можете узнать больше в предыдущем модуле , псевдоклассы привязываются к определенным состояниям , в которых может находиться элемент, а не к общим стилям частей этого элемента.

Интерактивные состояния

Следующие псевдоклассы применяются в зависимости от взаимодействия пользователя с вашей страницей.

:hover

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 2.

Source

Если у пользователя есть указывающее устройство, например, мышь или трекпад, и он наводит его на элемент, вы можете использовать это состояние с помощью :hover для применения стилей. Это полезный способ указать, что с элементом можно взаимодействовать.

:active

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 1.

Source

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

:focus , :focus-within и :focus-visible

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 1.

Source

Если элемент может получить фокус, например <button> , вы можете отреагировать на это состояние с помощью псевдокласса :focus .

Вы также можете отреагировать, если дочерний элемент вашего элемента получает фокус, с помощью :focus-within .

Фокусируемые элементы, такие как кнопки, будут отображать кольцо фокусировки, когда они находятся в фокусе, даже при нажатии. В такой ситуации разработчик применит следующий CSS:

button:focus {
    outline: none;
}

Этот CSS-код удаляет кольцо фокусировки по умолчанию в браузере, когда элемент получает фокус, что создает проблему доступности для пользователей, перемещающихся по веб-странице с помощью клавиатуры. Если стиль фокусировки отсутствует, пользователи не смогут отслеживать текущий фокус при использовании клавиши Tab . С помощью :focus-visible можно задать стиль фокусировки, когда элемент получает фокус с помощью клавиатуры, а также использовать правило outline: none , чтобы предотвратить фокусировку при взаимодействии с ним указателя.

button:focus {
    outline: none;
}

button:focus-visible {
    outline: 1px solid black;
}

:target

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 1.3.

Source

Псевдокласс :target выбирает элемент, id которого соответствует фрагменту URL. Допустим, у вас есть следующий HTML-код:

<article id="content">
    <!-- ... -->
</article>

Вы можете прикрепить стили к этому элементу, если URL содержит #content .

#content:target {
    background: yellow;
}

Это полезно для выделения областей, на которые можно было бы ссылаться напрямую, например, на основной контент веб-сайта, с помощью ссылки пропуска.

Исторические государства

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 1.

Source

Псевдокласс :link можно применить к любому элементу <a> , имеющему значение href , которое еще не было посещено.

:visited

Вы можете задать стиль для ссылки, по которой пользователь уже побывал, с помощью псевдокласса :visited . Это состояние противоположно :link , но из соображений безопасности доступно меньше CSS-свойств. Можно задать стиль только color , background-color , border-color , outline-color , а также для цветов fill и stroke SVG.

Порядок имеет значение

Если вы определяете стиль :visited , его можно переопределить псевдоклассом ссылки как минимум с такой же специфичностью. Поэтому рекомендуется использовать правило LVHA для стилизации ссылок с псевдоклассами в определённом порядке: :link , :visited , :hover , :active .

a:link {}
a:visited {}
a:hover {}
a:active {}

Форма состояния

Следующие псевдоклассы могут выбирать элементы формы в различных состояниях, в которых эти элементы могут находиться во время взаимодействия с ними.

:disabled и :enabled

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 3.1.

Source

Если элемент формы, например, <button> , отключен браузером, вы можете подключиться к этому состоянию с помощью псевдокласса :disabled . Псевдокласс :enabled доступен и для противоположного состояния, хотя элементы формы также имеют :enabled по умолчанию, поэтому вам может не понадобиться этот псевдокласс.

:checked и :indeterminate

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 3.1.

Source

Псевдокласс :checked доступен, когда поддерживающий элемент формы, такой как флажок или переключатель, находится в отмеченном состоянии.

Состояние :checked — это бинарное (истина или ложь), но у флажков есть промежуточное состояние, когда они ни отмечены, ни сняты. Это состояние называется :indeterminate .

Примером такого состояния является элемент управления «выбрать всё», который устанавливает все флажки в группе. Если пользователь затем снимет один из этих флажков, корневой флажок перестанет отображать состояние «все отмечены», поэтому его следует перевести в неопределённое состояние.

Элемент <progress> также имеет неопределённое состояние, которое можно стилизовать. Обычно его используют для придания ему полосатого вида, чтобы показать, что неизвестно, сколько ещё нужно.

:placeholder-shown

Browser Support

  • Хром: 47.
  • Край: 79.
  • Firefox: 51.
  • Сафари: 9.

Source

Если поле формы имеет атрибут placeholder и не имеет значения , псевдокласс :placeholder-shown можно использовать для назначения стилей этому состоянию. Как только в поле появляется контент, независимо от наличия placeholder , это состояние перестает применяться.

Состояния проверки

Browser Support

  • Хром: 10.
  • Край: 12.
  • Firefox: 4.
  • Сафари: 5.

Source

Вы можете реагировать на валидацию HTML-форм с помощью псевдоклассов, таких как :valid , :invalid и :in-range . Псевдоклассы :valid и :invalid полезны в таких контекстах, как поле электронной почты, которое должно соответствовать pattern , чтобы считаться валидным. Это состояние валидности значения можно показать пользователю, помогая ему понять, что он может безопасно перейти к следующему полю.

Псевдокласс :in-range доступен, если входные данные имеют min и max значения, например, числовые входные данные , и значение находится в пределах этих границ.

С помощью HTML-форм можно определить, что поле является обязательным, с помощью атрибута required . Псевдокласс :required будет доступен для обязательных полей. Необязательные поля можно выбрать с помощью псевдокласса :optional .

Выбор элементов по индексу, порядку и местоположению

Существует группа псевдоклассов, которые выбирают элементы в зависимости от их местоположения в документе.

:first-child и :last-child

Browser Support

  • Хром: 4.
  • Край: 12.
  • Firefox: 3.
  • Сафари: 3.1.

Source

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

:only-child

Browser Support

  • Хром: 2.
  • Край: 12.
  • Firefox: 1.5.
  • Сафари: 3.1.

Source

Вы также можете выбрать элементы, не имеющие родственных элементов, с помощью псевдокласса :only-child .

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

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 3.5.
  • Сафари: 3.1.

Source

Вы можете выбрать :first-of-type и :last-of-type , которые на первый взгляд выглядят так, будто делают то же самое, что и :first-child и :last-child , но рассмотрим следующий HTML-код:

<div class="my-parent">
    <p>A paragraph</p>
    <div>A div</div>
    <div>Another div</div>
</div>

И этот CSS:

.my-parent div:first-child {
    color: red;
}

Ни один элемент не будет окрашен в красный цвет, поскольку первый дочерний элемент — это абзац, а не div. В этом контексте полезен псевдокласс :first-of-type .

.my-parent div:first-of-type {
    color: red;
}

Несмотря на то, что первый <div> является вторым дочерним элементом, он все равно является первым типом внутри элемента .my-parent , поэтому по этому правилу он будет окрашен в красный цвет.

:nth-child и :nth-of-type

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 3.5.
  • Сафари: 3.1.

Source

Вы не ограничены первыми и последними дочерними элементами и типами. Псевдоклассы :nth-child и :nth-of-type позволяют указать элемент с определённым индексом. Индексация в селекторах CSS начинается с 1.

Псевдоклассы :nth-last-child() и :nth-last-of-type() отсчитываются с конца, а не с начала.

В эти псевдоклассы можно передавать не только индекс. Если нужно выбрать все чётные элементы, можно использовать :nth-child(even) .

Вы также можете создавать более сложные селекторы, которые находят элементы через равные интервалы, используя микросинтаксис An+B .

li:nth-child(3n+3) {
    background: yellow;
}

Этот селектор выбирает каждый третий элемент, начиная с элемента 3. В этом выражении n — это индекс, который начинается с нуля, а 3 ( 3n ) — это то, на что вы умножаете этот индекс.

Допустим, у вас есть 7 элементов <li> . Первым выбранным элементом будет элемент 3, поскольку 3n+3 преобразуется в (3 * 0) + 3 Следующая итерация выберет элемент 6, поскольку n теперь увеличилось до 1 , то есть (3 * 1) + 3) . Это выражение работает как для :nth-child , так и :nth-of-type .

:nth-child() и :nth-last-child() также поддерживают синтаксис «of S», позволяющий фильтровать совпадения по селектору, аналогично :nth-of-type() . li:nth-of-type(even) эквивалентно :nth-child(even of li) . В то время как :nth-of-type позволяет фильтровать только по типу элемента (например, li или p ), синтаксис «of S» позволяет фильтровать по любому селектору.

Если у вас есть таблица, возможно, стоит добавить полосы к каждой второй строке. Хотя можно выбрать каждую вторую строку с помощью tr:nth-child(even) , это не сработает, если вы отфильтровываете некоторые строки. Если вы реализуете фильтрацию с помощью атрибута hidden , можно добавить of :not([hidden]) к селектору, чтобы предварительно отфильтровать скрытые элементы перед выбором чётных строк.

tr:nth-child(even of :not([hidden])){
  background: lightgrey;
}

Вы можете поэкспериментировать с этим типом селектора в этом тестере nth-child или в этом инструменте выбора количества .

:only-of-type

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 3.5.
  • Сафари: 3.1.

Source

Наконец, вы можете найти единственный элемент определённого типа в группе одноуровневых элементов с помощью :only-of-type . Это полезно, если вы хотите выбрать списки, содержащие только один элемент, или найти единственный выделенный жирным шрифтом элемент в абзаце.

Поиск пустых элементов

Иногда может быть полезно идентифицировать совершенно пустые элементы, и для этого тоже есть псевдокласс.

:empty

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 3.1.

Source

Если у элемента нет дочерних элементов, к ним применяется псевдокласс :empty . Однако дочерние элементы — это не только HTML-элементы или текстовые узлы: они также могут быть пробелами, что может сбивать с толку при отладке следующего HTML-кода и возникновении вопросов, почему он не работает с :empty :

<div>
</div>

Причина в том, что между открывающим и закрывающим <div> есть пробелы, поэтому :empty не будет работать.

Псевдокласс :empty может быть полезен, если у вас ограниченный контроль над HTML-кодом и вы хотите скрыть пустые элементы, например, в WYSIWYG-редакторе. В данном случае редактор добавил лишний пустой абзац.

<article class="post">
 <p>Donec ullamcorper nulla non metus auctor fringilla.</p>
 <p></p>
 <p>Curabitur blandit tempus porttitor.</p>
</article>

С помощью :empty вы можете найти это и скрыть.

.post :empty {
    display: none;
}

Поиск и исключение нескольких элементов

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

:is()

Browser Support

  • Хром: 88.
  • Край: 88.
  • Firefox: 78.
  • Сафари: 14.

Source

Если вы хотите найти все дочерние элементы h2 , li и img в элементе .post , вы можете подумать о написании списка селекторов следующим образом:

.post h2,
.post li,
.post img {
    
}

С помощью псевдокласса :is() можно написать более компактную версию:

.post :is(h2, li, img) {
    /* ... */
}

Псевдокласс :is не только компактнее списка селекторов, но и более терпим к ошибкам. В большинстве случаев, если в списке селекторов есть ошибка или неподдерживаемый селектор, весь список селекторов перестанет работать. Если в переданных селекторах псевдокласса :is есть ошибка, он проигнорирует недопустимый селектор и использует допустимые.

:not()

Browser Support

  • Хром: 1.
  • Край: 12.
  • Firefox: 1.
  • Сафари: 3.1.

Source

Вы также можете исключать элементы с помощью псевдокласса :not() . Например, его можно использовать для оформления всех ссылок, у которых нет атрибута class .

a:not([class]) {
    color: blue;
}

Псевдокласс :not также может помочь улучшить доступность. Например, элемент <img> должен иметь атрибут alt , даже если это пустое значение, поэтому вы можете написать CSS-правило, которое добавляет толстую красную рамку к недопустимым изображениям:

img:not([alt]) {
    outline: 10px red;
}

:has()

Что делать, если вы хотите стилизовать элементы в зависимости от их содержимого? Для этого можно использовать псевдокласс :has() . Например, можно применить стили к кнопкам со значками.

 button:has(svg) {
  /* ... */
}

В самой простой конфигурации, как и в предыдущем примере, :has() можно рассматривать как родительский селектор. Вы также можете использовать соответствующий родительский селектор в сочетании с другими селекторами для выбора других элементов.

form:has(input:valid) label {
  font-weight: bold;
}

form:has(input:valid) label::after {
  content: "✅";
}

В этом примере мы применяем стили к элементу label и псевдоэлементу label::after , когда поле ввода формы имеет valid псевдокласс.

Псевдокласс :has() не может быть вложен в другой :has() , но его можно комбинировать с другими псевдоклассами.

:is(h1, h2, h3):has(a) {
   /* ... */
}

Список селекторов не прощает ошибок, поэтому, если какие-либо селекторы в списке недействительны, все правила стилей будут проигнорированы.

.my-element:has(img, ::before) {
  /* any styles here will be discarded since pseudo elements can't be included in the :has() selector list */
}

Проверьте свое понимание

Проверьте свои знания псевдоклассов

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

ЛОЖЬ
Истинный

Какой из перечисленных ниже псевдоклассов является функциональным ?

:empty
:is()
:not()
:target

Какие из следующих псевдоклассов обусловлены взаимодействием с пользователем?

:target
:hover
:focus-within
:press
:squeeze

Какие из следующих являются псевдоклассами состояния <form> ?

:loading
:in-range
:checked
:valid
:indeterminate
:fresh
:enabled