Объединение селекторов в цепочку с помощью :is
Обычная задача в CSS - применить некоторый стиль к нескольким селекторам. Было бы неплохо, если бы мы могли сократить количество повторений селекторов и указать основной только один раз. И оказывается, что мы можем!
Предположим, вы хотите применить тот же стиль к состояниям фокуса, наведения и какому-то значению атрибут элемента, например, для навигационной ссылки:
.nav-link:focus,
.nav-link:hover,
.nav-link[aria-current="page"] {}Для каждого нового селектора вам необходимо повторить базовый селектор (.nav-link).
Хотя в этом изолированном примере это может показаться несущественным, но чем больше специфики верстки, тем больше приходится писать CSS подобным образом. Кстати, стили еще разрастутся, если вам нужно использовать дополнительные модификаторы, например, с помощью :not:
.button:not(.disabled):focus,
.button:not(.disabled):hover {}Если вы используете Sass, то можете сказать, что там не все так плохо благодаря использованию амперсанда:
.nav-link {
&:focus,
&:hover,
&[aria-current="page"] {}
}Но спешу вас расстроить, вы все равно в конечном итоге отправляете тот же объем выходного CSS.
Было бы неплохо, если бы мы могли сократить количество повторений и указать основной селектор только один раз. И оказывается, что мы можем!
Все основные браузеры теперь поддерживают функцию псевдокласса :is.
Он принимает список селекторов, разделенных запятыми, для сопоставления, что позволяет вам писать меньше строк CSS для выполнения той же задачи, что и раньше.
Вот как выглядел бы наш предыдущий пример, если бы мы использовали :is:
.nav-link:is(:focus, :hover, [aria-current="page"]) {}Этот селектор будет соответствовать всем элементам с классом nav-link, которые также имеют псевдокласс :focus, псевдокласс :hover или атрибут aria-current="page". Это позволяет вам объединить все ваши стили для элемента в одном селекторе.
Мы также можем провести рефакторинг второго примера, где мы связали дополнительные модификаторы с помощью :not:
.button:not(.disabled):is(:focus, :hover) {}Это здорово, потому что это означает, что нам не нужно повторять какие-либо промежуточные классы или псевдоклассы — нам нужно только перечислить их один раз и связать в цепочку :is, чтобы предоставить дополнительный список селекторов.
Функция псевдокласса :is еще приятнее в Sass, поскольку вам вообще не нужно повторно вводить базовый селектор и вы можете просто использовать оператор амперсанда:
.nav-link {
/* основные стили */
&:is(:focus, :hover, [aria-current="page"]) {
/* стили активных состояний */
}
}Наконец, стоит отметить, что, хотя во всех примерах до сих пор рассматривалась цепочка :is с базовым селектором, на самом деле вы можете просто использовать :is самостоятельно. Например, в следующем CSS :is используется для получения прямых потомков определенных родительских селекторов:
:is(.parent1, .parent2, .parent3) > * {}Без использования :is пришлось бы написать вот так:
.parent1 > *,
.parent2 > *,
.parent3 > * {}Важные моменты
Специфичность (вес)
Во-первых , :is получает самую большую специфичность из своего списка аргументов.
Это означает, что он идеально подходит для ситуаций, когда все селекторы, которые вы перечисляете, имеют одинаковую специфику. Так обстоит дело в первом примере, который мы видели, где все селекторы имеют общую специфику класса:
.nav-link:is(:focus, :hover, [aria-current="page"]) {}Но в следующем примере общая специфичность :is оказывается выше из-за наличия id в первом списке селекторов, поэтому будущие селекторы с более низкой специфичностью будут переопределены:
<div class="class"></div>
div:is(#id, .class) {
background: red;
}
/* Всегда будет переопределено */
div:is(.class, .another-class) {
background: blue;
}В этом примере div в конечном итоге имеет красный цвет фона, а не синий, потому что id в первом селекторе увеличивает общую специфичность селектора.
Прощающий синтаксический анализ селектора
Во-вторых, :is использует прощающий синтаксический анализ селектора, что означает, что если один из перечисленных вами селекторов окажется недействительным, весь список аргументов не будет признан недействительным. Вот пример:
.element:is(:focus, :unrecognized-selector) {}:is по-прежнему будет анализировать список аргументов и применять стиль к элементу, если встречается допустимый селектор (в данном случае :focus).
На этом статья подходит к концу, надеюсь вы узнали для себя что-то новое!
Если вам хочется почитать и другие стать из рубрики #научите_меня_css, то не забывайте подписываться на мой телеграм канал и искать там по этому хештегу!
Читать еще:
- Введение в курс по three.js
- Красивый курсор при помощи CSS и JavaScript
- Используем forwardRef в React для оптимизации