CSS псевдокласс :is() — как и где его использовать

HTML и CSS
247 просмотров

CSS-псевдокласс :is() — инструмент для группировки селекторов. Вместо того чтобы дублировать одно и то же правило для каждого тега отдельно, вы перечисляете нужные элементы через запятую внутри :is() , и браузер применяет стиль к каждому из них. В этой статье разберём синтаксис селектора :is() , покажем, где он экономит больше всего кода, и объясним единственный нюанс, который стоит знать.

CSS псевдокласс :is() — группировка селекторов

Что такое псевдокласс :is() в CSS

:is() — CSS-псевдокласс из спецификации Selectors Level 4. Работает просто: в скобках пишете теги, классы или любые другие селекторы — браузер применяет стиль к каждому из них.

Посмотрите на два одинаковых по результату правила:

/* Обычный способ */
h1, h2, h3 {
    line-height: 1.3;
}

/* Через псевдокласс :is() */
:is(h1, h2, h3) {
    line-height: 1.3;
}

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

Зачем нужен селектор :is() — задача без него

Допустим, нужно стилизовать все ссылки внутри article , section и aside . Без :is() это три строки с одинаковым правилом:

article a,
section a,
aside a {
    text-decoration: underline;
}

С :is() — одна:

:is(article, section, aside) a {
    text-decoration: underline;
}

Чем больше родительских элементов и чем разнообразнее дочерние — тем сильнее выигрыш.

:is() с несколькими уровнями — где экономия максимальна

Если нужно охватить сразу несколько родителей и несколько дочерних элементов, CSS без :is() разрастается быстро. Три родителя, три заголовка — уже девять строк. Добавьте все шесть уровней h1–h6 — получите восемнадцать. С :is() это одна строка независимо от количества:

:is(article, section, aside) :is(h1, h2, h3, h4, h5, h6) {
    font-weight: bold;
}

Браузер сам раскрывает это правило во все восемнадцать комбинаций. Добавить main в список родителей — дописать одно слово.

Другой типичный сценарий — интерактивные состояния ссылок:

/* Было */
nav a:hover,
nav a:focus,
nav a:active {
    color: blue;
}

/* Стало */
nav a:is(:hover, :focus, :active) {
    color: blue;
}

Один нюанс: не мешайте классы и теги в одном :is()

В CSS классы ( .active ) «весомее» тегов ( p , span ) — они перебивают стили тегов при конфликте. Если положить классы и теги в один :is() вместе, всё правило получает вес класса — в том числе для тегов внутри. Это может неожиданно перебить ваши другие стили.

/* Проблема: p внутри :is() ведёт себя как класс,
   а значит перебьёт обычное правило для p */
:is(.active, p) { color: red; }
p { color: black; } /* этот стиль проиграет! */

/* Безопасно: держим классы и теги отдельно */
.active { color: red; }
p { color: black; }

Простое правило: если внутри :is() только теги — всё в порядке. Только классы — тоже. Мешать их в одном :is() стоит осознанно.

Хотите нулевую специфичность? Есть псевдокласс :where() — работает точно так же, как :is(), но не добавляет никакой специфичности. Идеально для базовых стилей дизайн-системы, которые легко должны перебиваться.

:is() и :not() — включение и исключение

:not() — обратная сторона медали: применить стили ко всему, кроме перечисленных элементов. Вместе они читаются почти как обычная речь.

Например, подчёркивать все ссылки в статье, кроме тех, что уже стилизованы как кнопки:

:is(article, section, aside) a:not(.btn) {
    text-decoration: underline;
}

С 2022 года :not() тоже принимает список через запятую — так что это полностью симметричная пара.

:is() против :where() — в чём разница

Есть псевдокласс-близнец — :where() . Синтаксис у него точно такой же, как у :is() , но он намеренно сделан «невесомым»: его стили проигрывают любому другому правилу для того же элемента.

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

/* :where() — «мягкий» стиль, его легко перебить */
:where(article, section) p {
    margin-bottom: 1rem;
}

/* Этот стиль победит, даже если он написан выше */
.intro p {
    margin-bottom: 0;
}

С :is() так не получится — его стиль имеет нормальный вес и будет конкурировать с остальными правилами. Для большинства задач подходит :is() , а :where() пригодится, когда нужны стили «по умолчанию», которые никому не мешают.

Практические примеры

Состояния полей формы. Несколько состояний сразу, без повторений:

input:is(:focus, :focus-visible) {
    outline: 2px solid blue;
    border-color: blue;
}

:is(input, textarea, select):is(:invalid, .is-error) {
    border-color: red;
}

Типографика в контенте. Единые отступы для всех текстовых блоков:

.content :is(p, ul, ol, blockquote, pre) {
    margin-bottom: 1.5rem;
}

.content :is(h2, h3, h4) {
    margin-top: 2.5rem;
    margin-bottom: 1rem;
}

Тёмная тема. Переключение цветов одним блоком:

[data-theme="dark"] :is(h1, h2, h3, p, li) {
    color: #f0f0f0;
}

[data-theme="dark"] a:is(:hover, :focus) {
    color: #93c5fd;
}

Поддержка браузерами

Сейчас CSS-селектор :is() поддерживается во всех современных браузерах без исключений:

  • Chrome — с версии 88 (январь 2021)
  • Firefox — с версии 78 (июнь 2020)
  • Safari — с версии 14 (сентябрь 2020)
  • Edge — с версии 88 (январь 2021)

По данным Can I Use поддержка составляет более 96% пользователей. Старые фоллбеки через :-webkit-any() и :matches() — это история, забудьте о них.

IE 11 :is() не поддерживает. Если вы до сих пор его поддерживаете — это отдельная история, и сочувствую.

:is() — простой инструмент, который сразу делает CSS чище и короче. Найдите в своём проекте длинный список одинаковых селекторов и замените — сами удивитесь, насколько лаконичнее станет код.

Вам может быть интересно:
Меш градиент CSS — сетчатый фон из нескольких radial-gradient
Как сделать меш градиент в CSS — Mesh gradient генератор
Вставка видео с Rutube на сайт — iframe и адаптивный embed
Как правильно вставить видео с RuTube на сайт
Полоса прокрутки страницы на CSS — пример готового индикатора
Как убрать или стилизовать полосу прокрутки — CSS скроллбар
Встраивание YouTube видео на сайт — адаптивный плеер на HTML и CSS
Добавляем YouTube видео на сайт
Комментарии 0 Разные мнения приветствуются. Здесь можно спорить и обсуждать, но уважительно и без токсичности.
Отмена