Ванильный код
March 29, 2022

Безопасный каскад стилей CSS с :where

В прошлой статье из цикла #научите_меня_css мы разобрали как объединять селекторы в цепочку с помощью :is, сегодня мы продолжим тему полезных псевдоклассов и разберем :where.

Так же как и :is, :where - это прощающая функция псевдокласса, которая принимает список селекторов, разделенных запятыми, для сопоставления.

Предположим, мы хотим написать следующий селектор:

.nav-link:focus,
.nav-link:hover,
.nav-link[aria-current="page"] {}

Используя :where это можно было бы написать вот так:

.nav-link:where(:focus, :hover, [aria-current="page"]) {}

Когда мы разбирали псевдокласс :is, то выяснили, что подобного эффекта можно добиться вот таким кодом:

.nav-link:is(:focus, :hover, [aria-current="page"]) {}

Однако, два эти варианта код не идентичны. Единственное различие между :is и :where заключается в том, что :is предполагает наивысшую специфичность из своего набора селекторов, тогда как :where всегда сводится к нулевой специфичности.

Если говорить проще, то вот это:

.nav-link {}

Будет иметь такую же специфичность, что и вот это:

.nav-link:where(:focus, :hover, [aria-current="page"]) {}

Интересно:
Если переходить к числам, то оба имеют 10 баллов числовой специфичности из-за класса .nav-link. Другими словами , :where не вносит никакой дополнительной специфичности в общий селектор.

Даже вот такой сложный и громоздкий селектор имеет нулевую специфичность:

:where(#id:not(.very.high.specificity).more.classes) {}

Так где же это использовать?

:where - очень хорошо подходит, когда вы хотите реализовать каскад переопределений. Фактически, один из отличных вариантов использования :where заключается в объявлении значений по умолчанию, которые гарантированно всегда будут иметь минимально возможную специфичность (ноль).

Например, Элад Шехтер использует эту технику в своем modern CSS reset для определения безопасных значений по умолчанию для определенных элементов. Вот как это может выглядеть на практике:

:where(ul, ol) {
  list-style: none;
}

:where(img) {
  max-width: 100%;
  height: auto;
}

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

Это правда, что в любом случае вы должны сначала объявлять значения по умолчанию (что-то вроде best practice), и редко вы когда-либо захотите стилизовать элементы, используя только имена тегов в другом месте вашей таблицы стилей (например, если вы используете методологию BEM). Но :where, по крайней мере, дает вам некоторый уровень уверенности в том, что определенные вами стили никогда не столкнутся с какими-либо конфликтами специфики.

На этом статья подходит к концу, надеюсь вы узнали для себя что-то новое!

Если вам хочется почитать и другие стать из рубрики #научите_меня_css, то не забывайте подписываться на мой телеграм канал и искать там по этому хештегу!

Читайте еще: