Селекторы CSS позволяют выбирать элементы по типу, атрибутам или местоположению в HTML-документе. В этом руководстве объясняются три новых параметра — :is(), :where() и :has().
Селекторы обычно используются в таблицах стилей. В следующем примере выполняется поиск всех <p> элементов абзаца и изменение веса шрифта на полужирный:
p {
font-weight : bold;
}
Вы также можете использовать селекторы в JavaScript для поиска узлов DOM:
document.querySelector() возвращает первый соответствующий элемент HTML document.querySelectorAll() возвращает все соответствующие HTML-элементы в виде массива NodeList. Селекторы псевдоклассов нацеливаются на элементы HTML на основе их текущего состояния. Возможно, наиболее известным является :hover, который применяет стили, когда курсор перемещается по элементу, поэтому он используется для выделения кликабельных ссылок и кнопок. Среди других популярных вариантов :
:visited: соответствует посещенным ссылкам :target: соответствует элементу, указанному в URL-адресе документа. :first-child: нацелен на первый дочерний элемент :nth-child: выбирает определенные дочерние элементы :empty: соответствует элементу без содержимого или дочерних элементов :checked: соответствует включенному флажку или переключателю :blank: стилизует пустое поле ввода :enabled: соответствует включенному полю ввода :disabled: соответствует отключенному полю ввода :required: нацелен на обязательное поле ввода :valid: соответствует допустимому полю ввода :invalid: соответствует недопустимому полю ввода :playing: нацеливается на воспроизводимый аудио- или видеоэлемент. Недавно браузеры получили еще три селектора псевдоклассов…
CSS: это селектор псевдокласса Примечание: изначально это было указано как :matches()и :any(), но :is()стало стандартом CSS.
Часто вам нужно применить один и тот же стиль к нескольким элементам. Например, <p> текст абзаца по умолчанию черный, но серый, когда он появляется внутри <article>
, <section>
, и <aside>
p {
color : #000 ;
}
article p,
section p,
aside p {
color : #444 ;
}
Это простой пример, но более сложные страницы приведут к более сложным и подробным строкам селектора. Синтаксическая ошибка в любом селекторе может нарушить стиль всех элементов.Препроцессоры CSS, такие как Sass, допускают вложение (что также входит в собственный CSS ): article, section, aside {
p {
color : #444 ;
}
}
Это создает идентичный код CSS, снижает трудоемкость ввода и может предотвратить ошибки. Но:
Пока не появится нативная вложенность, вам понадобится инструмент сборки CSS. Вы можете использовать такой вариант, как Sass, но это может создать сложности для некоторых команд разработчиков. Вложенность может вызвать другие проблемы. Легко создавать глубоко вложенные селекторы, которые становится все труднее читать, и выводить подробный CSS. :is()предоставляет собственное решение CSS, которое полностью поддерживается во всех современных браузерах (кроме IE):
:is ( article, section, aside) p {
color : #444 ;
}
Один селектор может содержать любое количество :is()псевдоклассов. Например, следующий сложный селектор применяет зеленый цвет текста ко всем элементам, и, которые являются <h1>дочерними <h2>элементами элемента, имеющего класс или и не являющегося первым дочерним элементом элемента :<p><section>.primary.secondary<article>:
article section:not ( :first-child ) :is ( .primary , .secondary ) :is ( h1, h2, p) {
color : green ;
}
Эквивалентный код без :is() обязательных шести селекторов CSS: article section.primary :not ( :first-child ) h1,
article section.primary :not ( :first-child ) h2,
article section.primary :not ( :first-child ) p,
article section.secondary :not ( :first-child ) h1,
article section.secondary :not ( :first-child ) h2,
article section.secondary :not ( :first-child ) p {
color : green ;
}
Обратите внимание, что :is()не могут сопоставляться ::beforeи ::afterпсевдоэлементы, поэтому этот пример кода завершится ошибкой:
div:is ( ::before , ::after ) {
display : block;
content : '' ;
width : 1 em ;
height : 1 em ;
color : blue ;
}
CSS :where Селектор псевдокласса :where()Синтаксис селектора идентичен :is()и также поддерживается во всех современных браузерах (кроме IE). Это часто приводит к идентичному стилю. Например:
:where ( article, section, aside) p {
color : #444 ;
}
Отличие в специфичности. Специфика — это алгоритм, используемый для определения того, какой селектор CSS должен переопределять все остальные. В следующем примере article p более конкретен, чем pодин, поэтому все элементы абзаца внутри
article p { color : #444 ; }
p { color : #000 ; }
В случае :is() специфичность — это наиболее конкретный селектор, найденный в его аргументах. А в случае :where()специфичность равна нулю.
Рассмотрим следующий CSS:
article p {
color : black ;
}
:is ( article, section, aside) p {
color : red ;
}
:where ( article, section, aside) p {
color : blue ;
}
Давайте применим этот CSS к следующему HTML:
< article>
< p> paragraph text</ p>
</ article>
Селектор :is() имеет ту же специфику, что и article p, но он появляется позже в таблице стилей, поэтому текст становится красным. Чтобы применить синий цвет, необходимо удалить оба селектора article pи, потому что селектор менее специфичен, чем любой из них.:is():where()
Будет использоваться больше кодовых баз, :is()чем :where(). Тем не менее, нулевая специфичность :where()может быть практичной для сбросов CSS, которые применяют базовые стандартные стили, когда нет доступных конкретных стилей. Как правило, при сбросе применяются шрифт, цвет, отступы и поля по умолчанию.
Этот код сброса CSS применяет верхнее поле 1emк <h2>заголовкам, если они не являются первыми дочерними <article>элементами элемента:
h2 {
margin-block-start : 1 em ;
}
article :first-child {
margin-block-start : 0 ;
}
Попытка установить пользовательское <h2> верхнее поле позже в таблице стилей не имеет никакого эффекта, потому что article :first-childимеет более высокую специфичность:
h2 {
margin-block-start : 2 em ;
}
Вы можете исправить это, используя селектор с более высокой специфичностью, но это больше кода и не обязательно очевидно для других разработчиков. В конце концов вы забудете, зачем вам это нужно:
article h2:first-child {
margin-block-start : 2 em ;
}
Вы также можете решить проблему, применив !importantк каждому стилю, но избегайте этого! Это значительно усложняет дальнейшее моделирование и разработку:
h2 {
margin-block-start : 2 em !important ;
}
Лучший выбор — принять нулевую специфичность :where()в вашем сбросе CSS:
:where ( h2) {
margin-block-start : 1 em ;
}
:where ( article :first-child ) {
margin-block-start : 0 ;
}
Теперь вы можете переопределить любой стиль сброса CSS независимо от его специфики; нет необходимости в дополнительных селекторах или !important:
h2 {
margin-block-start : 2 em ;
}
CSS: имеет селектор псевдокласса Селектор :has()использует синтаксис, аналогичный :is()и :where(), но он нацелен на элемент, который содержит набор других элементов. Например, вот CSS для добавления синей двухпиксельной рамки к любой <a>ссылке, содержащей один или несколько тегов <img>или :<section>
a:has ( img, section) {
border : 2 px solid blue ;
}
Это самая захватывающая разработка CSS за последние десятилетия! Наконец-то у разработчиков появился способ ориентироваться на родительские элементы!
Неуловимый «родительский селектор» был одной из наиболее востребованных функций CSS, но он создает проблемы с производительностью для поставщиков браузеров, и поэтому он давно появился. Проще говоря:
Браузеры применяют стили CSS к элементу, когда он отображается на странице. Поэтому весь родительский элемент должен быть перерисован при добавлении дополнительных дочерних элементов. Добавление, удаление или изменение элементов в JavaScript может повлиять на стиль всей страницы вплоть до прилагаемого файла. Предполагая, что поставщики решили проблемы с производительностью, введение :has()открывает возможности, которые были бы невозможны без JavaScript в прошлом. Например, вы можете установить стили внешней формы <fieldset>и следующей кнопки отправки, когда какое-либо обязательное внутреннее поле недействительно:
fieldset:has ( :required :invalid ) {
border : 3 px solid red ;
}
fieldset:has ( :required :invalid ) + button[ type = 'submit' ] {
opacity : 0.2 ;
cursor : not-allowed;
}
В этом примере добавляется индикатор подменю навигационной ссылки, который содержит список элементов дочернего меню:
nav li:has ( ol, ul) a::after {
display : inlne-block;
content : ">" ;
}
Или, возможно, вы могли бы добавить стили отладки, такие как выделение всех
/* where’s my image?! */
figure:not ( :has ( img) ) {
border : 3 px solid red ;
}
Прежде чем прыгнуть в редактор и провести рефакторинг кодовой базы CSS, имейте в виду, что :has()это новшество и поддержка более ограничена, чем для :is()и :where(). Он доступен в Safari 15.4+ и Chrome 101+ под экспериментальным флагом, но к 2023 году он должен стать широко доступным.
Заключение Селекторы псевдоклассов :is()и :where()упрощают синтаксис CSS. У вас будет меньше потребности во вложенности и препроцессорах CSS (хотя эти инструменты предоставляют другие преимущества, такие как частичные, циклы и минимизация).