Как работают CSS псевдоклассы :is, :where и :has

Как работают CSS псевдоклассы :is, :where и :has

От автора: CSS селекторы позволяют выбирать элементы по типу, атрибутам и положению внутри HTML-документа. В этом уроке разберем три новые опции — :is(), :where() и :has().

Селекторы в стилях применяются повсеместно. Пример ниже находит все параграфы и меняет жирность шрифта на bold:

Для поиска DOM узлов селекторы можно использовать и в JavaScript:

document.querySelector() возвращает первый найденный HTML элемент

document.querySelectorAll() возвращает все найденные HTML элементы в структуре похожей на массив NodeList

Псевдоклассы находят HTML элементы по их текущему состоянию. Наверное, самый известный псевдокласс — :hover. Он применяет стили к элементу, когда курсор наводится на него. Его используют для подсветки кликабельных ссылок и кнопок. Есть и другие популярные опции:

:visited: находит посещенные ссылки

:target: находит элементы, помеченные ссылкой

:first-child: находит первый дочерний элемент

:nth-child: выбирает заданный дочерний элемент

:empty: находит элемент без контента или без дочерних элементов

:checked: находит включенные чекбоксы и радиокнопки

:blank: стилизует пустые поля ввода

:enabled: находит активные input поля

:disabled: находит неактивные input поля

:required: находит input поля обязательные для заполнения

:valid: находит input поля с валидным введенным значением

:invalid: находит input поля с невалидным введенным значением

:playing: находит элементы, проигрывающие аудио или видео

CSS псевдокласс :is

Обратите внимание: в ранних версиях селектор писался по-другому — :matches() и :any(), но позже стандартом стал :is().

Очень часто нужно применять одинаковые стили ко множеству элементов. Например, текст внутри <p> должен быть черный, но внутри <article>, <section> или <aside> текст будет серый:

Это простой пример, однако более сложные страницы усложнят и селекторы. Синтаксическая ошибка в одном селекторе поломает стили для всех элементов. CSS препроцессоры типа Sass разрешают использовать вложенность (что также появится в нативном CSS):

Этот CSS идентичен коду выше. Однако такой код писать легче, и он снижает вероятность ошибок. Но есть нюансы:

Пока эта функция не появилась в нативном CSS, придется использовать CSS билд инструменты. Можно использовать Sass, но это может усложнить работу в некоторых командах разработки.

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

:is() дает нам нативное CSS решение с поддержкой во всех современных браузерах (без IE):

Один селектор может содержать любое количество псевдоклассов :is(). Например, сложный селектор ниже применяет зеленый текст ко всем <h1>, <h2> и <p> элементам, которые расположены внутри <section> с классом .primary или .secondary. А также эти элементы должны быть не первым дочерним элементом <article>:

Аналогичный код без :is() требует 6 CSS селекторов:

Обратите внимание, :is() не может использоваться с псевдоэлементами ::before и ::after. Код ниже упадет с ошибкой:

CSS псевдокласс :where

Синтаксис :where() аналогичен :is() и также поддерживается во всех современных браузерах (без IE). Очень часто результат его работы будет таким же, как у предыдущего псевдокласса. Например:

Разница в специфичности. Специфичность – алгоритм, определяющий приоритет перезаписи CSS селекторов. В примере ниже «article p» более специфичен чем просто «p». Поэтому все параграфы внутри article будут серыми:

Для :is() специфичность равна самому специфичному селектору внутри. Для :where() специфичность равно нулю. Разберем CSS код ниже:

Применим этот код к HTML:

Текст будет красным, как показано в демо ниже:

:is() имеет одинаковую специфичность как и article p, но в коде псевдокласс расположен ниже, поэтому текст будет красным. Чтобы применить синий цвет, нужно удалить article p и :is(), ведь :where() наименее специфичный.

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

Пример CSS сброса ниже применяет top margin в 1em к заголовкам h2 за исключением ситуаций, когда заголовки являются первым дочерними элементами от article:

Если ниже попробовать применить свое значение для top margin у h2, у нас не получится, так как article :first-child имеет специфичность выше:

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

Также проблему решит !important для всех необходимых стилей, но не делайте так! Дальнейшее написание стилей и разработка станут только сложнее:

Лучше воспользоваться нулевой специфичностью :where() при сбросе:

Теперь можно переписывать любые стили из сброса, не обращая внимания на их специфичность. Больше не нужно писать !important:

CSS псевдокласс :has

Синтаксис :has() похож на :is() и :where(), но этот псевдокласс находит элемент, который содержит набор других элементов. Например, ниже стили, применяющие синюю рамку в 2 пикселя ко всем <a>, внутри которых есть один или более <img> или <section>:

Это самая классная доработка CSS за десятилетия! Разработчики, наконец, могут находить родительские элементы!

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

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

Добавление, удаление или изменение элементов в JS затрагивает стили всей страницы вплоть до закрывающего body.

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

Как работают CSS псевдоклассы :is, :where и :has

Этот пример добавляет индикатор в подменю ссылок, которое содержит список дочерних элементов меню:

Возможно, вы хотели бы добавить стили для дебага. Например, подсветить все элементы figure без вложенного img:

Как работают CSS псевдоклассы :is, :where и :has

Пока вы не открыли свой CSS в редакторе, добавлю, что :has() это новый псевдокласс и его поддержка хуже чем :is() и :where(). Он работает в Safari 15.4+ и Chrome 101+ под экспериментальным флагом. В 2023 ожидается широкая поддержка.

Заключение

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

:has() – более революционный селектор. Поиск родительского элемента быстро станет популярен, и мы забудем о темных временах! Мы опубликуем полный урок по :has(), когда он станет доступен во всех современных браузерах.

Автор: Craig Buckler

Источник: www.sitepoint.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии запрещены.