Забудь про селекторы-простыни: Укрощаем CSS с помощью :is() и :where()
Слушай, вспомни тот момент, когда ты открываешь чужой (или свой полугодовалый) проект и видишь там селектор длиной в три строки. Что-то вроде header h1, header h2, footer h1, footer h2, section h1... и так далее. Это выглядит как список покупок, в котором легко запутаться, а поддерживать такую «красоту» — то еще удовольствие. Раньше мы просто мирились с этим или прятали проблему за вложенностью в Sass, но браузеры-то все равно получали на вход этот огромный неповоротливый ком кода.
Сегодня я покажу тебе, как выкинуть этот мусор и писать селекторы, которые выглядят чисто, работают эффективно и не заставляют твои глаза кровоточить. Погнали разбираться с :is() и :where().
Как мы страдали раньше
До появления этих псевдоклассов у нас было два пути, и оба вели в тупик. Либо ты вручную перечислял все комбинации через запятую, либо использовал препроцессоры. Но у препроцессоров была ловушка: когда ты пишешь красивую вложенность в SCSS, на выходе получается монструозный CSS-файл, который весит больше, чем должен.
Еще одна боль — специфичность. Если в твоем длинном списке один селектор оказывался невалидным (например, опечатка в нестандартном псевдоэлементе), весь блок стилей просто отваливался. К тому же, управление приоритетами превращалось в войну !important. Чтобы по-настоящему взять специфичность под контроль, советую глянуть статью про Cascade Layers (@layer) в CSS — это идеальное дополнение к тому, о чем мы говорим сегодня.
Как делать правильно в 2026 году
Современный подход — это использование :is() для группировки и :where() для обнуления специфичности.
- :is() — берет специфичность самого «сильного» селектора в своем списке. Он делает код компактным и, что самое крутое, если один селектор в списке невалиден, браузер не проигнорирует все правило, а просто пропустит «сломанную» часть.
- :where() — делает ровно то же самое, но его специфичность всегда равна нулю. Это просто маст-хэв для сбросов стилей (resets) и библиотек компонентов, чтобы пользователи могли легко переопределять твои стили без костылей.
Кстати, если ты любишь чистоту не только в селекторах, но и в типографике, зацени материал про text-wrap: balance и pretty, это сделает твои заголовки еще сексуальнее.
Готовый сниппет кода
Давай сравним старый подход и новый. Посмотри, насколько чище становится структура:
/* Раньше: Громоздко и сложно поддерживать */
header .title,
header .subtitle,
section .title,
section .subtitle,
footer .title,
footer .subtitle {
color: var(--primary-color);
font-family: sans-serif;
}
/* Сейчас с :is(): Элегантно и читаемо */
:is(header, section, footer) :is(.title, .subtitle) {
color: var(--primary-color);
font-family: sans-serif;
}
/* С :where(): Стили с нулевой специфичностью для легкого переопределения */
:where(article, aside) p {
line-height: 1.6;
margin-bottom: 1rem;
}
Частая ошибка новичков
Самый частый затык — непонимание разницы в специфичности. Новички часто используют :is() там, где нужно было использовать :where(), и наоборот.
Запомни: если ты пишешь стили для UI-кита или базовые стили темы, которые должны легко перебиваться любым кастомным классом — используй :where(). Если же ты просто хочешь сократить запись в логике основного приложения — бери :is(). И никогда не забывай: :is(.class, #id) получит специфичность ID, даже если ты применяешь его к элементу с классом. В этом коварство :is() — он всегда равняется на самого мощного парня в своей компании.
🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!