Псевдокласс :has()
При изучении комбинаций селекторов мы столкнулись с тем, что с их помощью можно выбрать дочерний или следующий братский элемент, но никак не родителя или предыдущий элемент.
Селекторы потомка и дочерние селекторы читаются слева направо, следующая запись означает, что следует найти все элементы <button>, внутри них <span> и стиль применить уже к ним.
button > span { color: red; }
В CSS не существует селектора родителя, позволяющего применить стиль к родителю при наличии у него указанного дочернего элемента. Роль такого селектора выполняет псевдокласс :has().
Псевдокласс :has() применяет стилевые правила к элементу, если у него есть указанный потомок или родственный элемент. Это даёт возможность задавать стили родителя на основе его дочерних элементов. К примеру, следующая запись означает применить стиль к элементу <li>, если внутри него располагается элемент <a>.
li:has(a) { background-color: tomato; }
Вот несколько примеров использования псевдокласса :has().
a:has(> img) {…}
Применяет стиль к элементам <a>, которые являются родителями для <img>.
button:has(.icon)
Применяет стиль к элементам <button>, внутри которых есть элемент с классом .icon.
h1:has(+ h2)
Применяет стиль к элементам <h1>, после которых идёт элемент <h2>.
li:has(+ li:hover)
Применяет стиль к предыдущему пункту списка (<li>) при наведении.
.card:not(:has(img))
Применяет стиль ко всем элементам с классом .card, внутри которых нет элемента <img>.
article:has(audio, video)
Применяет стиль к элементам <article> внутри которых есть элемент <audio> или <video>.
:is(h1, h2, h3):has(+ p)
Применяет стиль к элементам <h1>, <h2>, <h3>, после которых сразу идёт элемент <p>.
Как видно из приведённых примеров, внутрь :has() можно вставлять группу селекторов, дочерние селекторы, смежные селекторы и др.
Внутри :has() не разрешается вставлять другой :has(), а также псевдоэлементы (::first-line, ::before, ::after и др.).
:has(:has(li)) { /* Неверно */ } :has(::before) { /* Неверно */ }
В примере 1 при наведении курсора мыши на картинку все остальные изображения в блоке .photo становятся полупрозрачными. Это делается с помощью комбинации псевдоклассов :has(), :not() и :hover().
Пример 1. Использование :has()
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>:has</title>
<style>
.photo:has(img:hover) img:not(:hover) {
opacity: 0.3; /* Значение прозрачности */
}
</style>
</head>
<body>
<div class="photo">
<img src="image/thumb1.jpg" alt="">
<img src="image/thumb2.jpg" alt="">
<img src="image/thumb3.jpg" alt="">
<img src="image/thumb4.jpg" alt="">
</div>
</body>
</html>
Итоги
- Псевдокласс :has() позволяет выбрать элементы на основе того, содержат ли они определённый дочерний элемент или нет.
- :has() допустимо комбинировать с группой селекторов (p:has(b, i)), селектором потомка (li:has(a)), дочерним селектором (li:has(>li)), смежным селектором (li:has(+ li)) и др.
- :has() может применяться совместно с другими псевдоклассами, например, :hover (span:has(a:hover)), :is() (:is(h1, h2):has(+ p)), :not() (figure:not(:has(figcaption)) ) и др.
- Внутрь :has() нельзя вставлять другой :has(), а также псевдоэлементы (::first-line, ::before, ::after и др.).