Псевдокласс :has()

Псевдокласс :has() применяет стилевые правила к элементу, если у него есть указанный потомок или родственный элемент. Это даёт возможность задавать стили родителя на основе его дочерних элементов.

Вот несколько примеров использования псевдокласса :has().

Выделение цветом фона элемента <label> при поставленной в поле формы галочке.

<style> label:has(input[type="checkbox"]:checked) { background-color: bisque; } </style> <label><input type="checkbox"> Поставьте галочку</label>

Подсветка пункта меню с активной ссылкой.

<style> .menu { display: flex; list-style: none; } .menu li { padding: 0.5em; } .menu li:has(a.is-active) { background-color: tomato; } </style> <ul class="menu"> <li><a href="#">Главная</a></li> <li><a href="#" class="is-active">Сервис</a></li> <li><a href="#">Цена</a></li> </ul>

Изменение размера фотографии при наведении, также меняется размер предыдущей и следующей фотографий.

<style> .photo img { transition: 0.3s ease-in-out; margin: 1em; } .photo img:hover { transform: scale(1.3); position: relative; z-index: 2; } .photo img:hover + img { transform: scale(1.1); } .photo img:has(+ img:hover) { transform: scale(1.1); } </style> <div class="photo"> <img src="image/kyiv1.jpg" alt="" width="200"> <img src="image/kyiv2.jpg" alt="" width="200"> <img src="image/kyiv3.jpg" alt="" width="200"> <img src="image/kyiv4.jpg" alt="" width="200"> <img src="image/kyiv5.jpg" alt="" width="200"> <img src="image/kyiv6.jpg" alt="" width="200"> </div>

Изменение стиля предыдущих двух пунктов списка и двух последующих пунктов списка при наведении.

<style> ul li { transition: 0.2s ease-in; margin-bottom: 0.5rem; } ul li:hover { font-size: 1.6rem; } ul li:hover + li { font-size: 1.4rem; } ul li:hover + li + li{ font-size: 1.2rem; } ul li:has(+ li:hover) { font-size: 1.4rem; } ul li:has(+ li + li:hover) { font-size: 1.2rem; } </style> <ul> <li>Зевс</li> <li>Гера</li> <li>Посейдон</li> <li>Аид</li> <li>Деметра</li> <li>Гестия</li> <li>Аполлон</li> <li>Арес</li> <li>Артемида</li> <li>Афина</li> <li>Афродита</li> <li>Гермес</li> </ul>

Синтаксис

Селектор:has(<селектор>) { … }
Описание Пример
<тип> Указывает тип значения. <размер>
A && B Значения должны выводиться в указанном порядке. <размер> && <цвет>
A | B Указывает, что надо выбрать только одно значение из предложенных (A или B). normal | small-caps
A || B Каждое значение может использоваться самостоятельно или совместно с другими в произвольном порядке. width || count
[ ] Группирует значения. [ crop || cross ]
* Повторять ноль или больше раз. [,<время>]*
+ Повторять один или больше раз. <число>+
? Указанный тип, слово или группа не является обязательным. inset?
{A, B} Повторять не менее A, но не более B раз. <радиус>{1,4}
# Повторять один или больше раз через запятую. <время>#

Значения

Внутри :has() допустимо использовать селекторы, а также их комбинации. Вот несколько примеров:

  • a:has(img) — выберет элемент <a>, внутри которого располагается <img>;
  • button:has(.icon) — выберет элемент <button>, внутри которого есть элемент с классом .icon;
  • label:has(input:checked) — выберет элемент <label>, внутри которого помечено поле формы;
  • 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(), а также псевдоэлементы (::before, ::after).

Пример

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>:has</title> <style> figure { display: inline-block; /* Строчно-блочные элементы */ box-shadow: 0 0 5px rgba(0, 0, 0, 0.5); /* Параметры тени */ border-radius: 10px; /* Радиус скругления */ background-color: #eee; /* Цвет фона */ vertical-align: top; /* Выравнивание по верхнему краю */ img { display: block; /* Блочный элемент */ border-radius: 10px 10px 0 0; /* Радиус скругления */ } } figcaption { padding: 1em; /* Расстояние от текста до края */ } /* Для изображений без подписи */ figure:not(:has(figcaption)) img { border-radius: 10px; /* Радиус скругления */ } </style> </head> <body> <div class="photos"> <figure> <img src="image/aquaria1.jpg" alt=""> <figcaption>Морская черепаха</figcaption> </figure> <figure> <img src="image/aquaria2.jpg" alt=""> </figure> </div> </body> </html>

В данном примере используется разный стиль для карточки с подписью и без неё.

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>:has</title> <style> .photo img { transition: 1s; /* Время перехода */ } .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>

В данном примере при наведении курсора мыши на картинку все остальные изображения в блоке .photo становятся полупрозрачными.

Спецификация

Selectors Level 4

Браузеры

105 105 91 15.4 121
105 121 72 15.4

В таблице браузеров применяются следующие обозначения.

  • — элемент полностью поддерживается браузером;
  • — элемент браузером не воспринимается и игнорируется;
  • — при работе возможно появление различных ошибок, либо элемент поддерживается с оговорками.

Число указывает версию браузреа, начиная с которой элемент поддерживается.