Кратко
Секция статьи "Кратко"Псевдокласс :has
позволяет выбрать элемент, уточнив основной селектор дополнительным, и при этом не увеличив его «вес». В отличие от привычных селекторов, правило применится только к тому селектору, который был описан до :has
.
Пример
Секция статьи "Пример"Правила применятся только к такому <dt>
, за которым сразу следует другой элемент <dd>
:
dt:has(+ dd) { /* Стили */}
dt:has(+ dd) { /* Стили */ }
В отличие от соседнего селектора +
(dt + dd
), будет выбран не второй элемент, а первый, т. е. :has
позволяет буквально инвертировать селектор — правило применится не к последнему селектору, а к тому, который указан перед :has
.
Как, например, найти такие ссылки, внутри которых есть изображения:
a:has(img) { /* Стили */}
a:has(img) { /* Стили */ }
Как пишется
Секция статьи "Как пишется"selector1:has(selector2) { /* … */}
selector1:has(selector2) { /* … */ }
selector1
— необязательный селектор (если не указан — правило применится ко всем подходящим элементам). Аргумент selector2
в :has
описывает селектор относительно своей точки отсчёта — selector1
.
Как понять
Секция статьи "Как понять"По сути псевдокласс :has
позволяет уточнить основной селектор дополнительным селектором любой сложности.
Подсказки
Секция статьи "Подсказки"💡 Использование :has
не влияет на специфичность, т. е. при расчёте веса селектора учитывается только целевой селектор, к которому применяется этот псевдокласс.
На практике
Секция статьи "На практике"советует Секция статьи "Саша Патлух советует"
🛠 Бывает, что контент какого-то блока вашей HTML-страницы генерируется из Markdown-разметки. Это особенно часто встречается на сайтах, созданных при помощи генераторов сайтов вроде 11ty. Вы не можете добавить в сгенерированный HTML-код классы, идентификаторы или дата-атрибуты. Псевдокласс :has
может решить достаточно сложную ситуацию с непредвиденным появлением обёрток вокруг элементов.
Вот типовой кусок разметки Markdown:
## Цитаты Далай ЛамыЛюди были созданы для того, чтобы их любили,а вещи были созданы для того, чтобы ими пользовались.Мир в хаосе, потому что все наоборот.Принимая решение, спрашивайте себя: «А сделает ли это меня счастливым?»Задавая этот вопрос всякий раз перед принятием решения,мы перемещаем свое внимание с того, в чем мы себе отказываем,на то, к чему мы стремимся.Далай Лама
## Цитаты Далай Ламы Люди были созданы для того, чтобы их любили, а вещи были созданы для того, чтобы ими пользовались. Мир в хаосе, потому что все наоборот.  Принимая решение, спрашивайте себя: «А сделает ли это меня счастливым?» Задавая этот вопрос всякий раз перед принятием решения, мы перемещаем свое внимание с того, в чем мы себе отказываем, на то, к чему мы стремимся. Далай Лама
Эта разметка превратится в такой HTML (я поместил его внутрь секции — это похоже на реальное использование):
<section class="content"> <h2>Цитаты Далай Ламы</h2> <p> Люди были созданы для того, чтобы их любили, а вещи были созданы для того, чтобы ими пользовались. Мир в хаосе, потому что все наоборот. </p> <p> <img src="https://yoursite.com/dalai-lama.jpg" alt="Фото Далай Ламы" > </p> <p> Принимая решение, спрашивайте себя: «А сделает ли это меня счастливым?» Задавая этот вопрос всякий раз перед принятием решения, мы перемещаем свое внимание с того, в чем мы себе отказываем, на то, к чему мы стремимся. </p> <p>Далай Лама</p></section>
<section class="content"> <h2>Цитаты Далай Ламы</h2> <p> Люди были созданы для того, чтобы их любили, а вещи были созданы для того, чтобы ими пользовались. Мир в хаосе, потому что все наоборот. </p> <p> <img src="https://yoursite.com/dalai-lama.jpg" alt="Фото Далай Ламы" > </p> <p> Принимая решение, спрашивайте себя: «А сделает ли это меня счастливым?» Задавая этот вопрос всякий раз перед принятием решения, мы перемещаем свое внимание с того, в чем мы себе отказываем, на то, к чему мы стремимся. </p> <p>Далай Лама</p> </section>
Изображение обёрнуто в абзац, это неудобно, но так работает конвертер. Это усложняет стилизацию. Например, мы хотим поставить изображение справа от первого абзаца, а остальные абзацы не трогать. Псевдокласс :has
— помощник в таких случаях.
Выбираем абзац, следом за которым сразу идёт другой абзац с вложенным изображением:
.content p:has(+ p > img) { display: inline-block; vertical-align: top;}
.content p:has(+ p > img) { display: inline-block; vertical-align: top; }
Если знаки +
и >
в селекторах вызывают недоумение, то почитайте статью о комбинированных селекторах.
Теперь выберем абзац с вложенным изображением:
.content p:has(img) { display: inline-block; vertical-align: top; width: 300px;}
.content p:has(img) { display: inline-block; vertical-align: top; width: 300px; }
Подгоним изображение под ширину родителя:
.content img { width: 100%;}
.content img { width: 100%; }
советует Секция статьи "Realetive советует"
🛠 До появления псевдокласса :has
единственной возможностью управлять проверкой вложенного селектора был JavaScript.