На протяжении большей части истории CSS при помощи селекторов можно было нацеливаться на элементы, базируясь на их родителях в дереве DOM. Рассмотрим эту структуру HTML:
<div> <p>Paragraph 1</p> <div> <main> <div> <p>Paragraph 2</p> </div> <main>
Применить стили ко второму абзацу (Paragraph 2) в CSS очень просто, так как можно привязаться к родительскому узлу <main>
.
main p { color: blue; }
Это изменит стиль Paragraph 2, но не Paragraph 1, поскольку именно второй параграф содержится внутри элемента <main>
.
Однако исторически сложилось так, что стилизация узла <main>
в зависимости от наличия тега <p>
под ним не была простой.
<main> Это не надо стилизовать </main> <main> <p>А это - надо</p> </main>
Если смотреть вверх по дереву DOM, то не было способа применить стили только ко второму элементу <main>
, не задев первый (без использования классов или идентификаторов, конечно).
Представляем селектор :has()
По своей сути селектор :has() является реляционным псевдоклассом. Это означает, что он позволяет выбрать элемент на основе его отношений с другими элементами. В частности, он выбирает элемент, если тот содержит другой элемент, соответствующий заданному селектору.
В приведенном выше примере мы можем сделать следующее:
main:has(p) { color: blue; }
Это открывает много возможностей для более эффективного оформления веб-страниц с использованием меньшего количества кода.
Пример 1. Выделение статей с помощью изображений
Рассмотрим веб-страницу, на которой отображается список статей, каждая из которых заключена в тег <article>
. Если мы хотим выделить статьи, содержащие изображения, селектор :has() предлагает простое решение:
article:has(img) { border: 2px solid blue; }
See the Pen Has Selector in CSS — Example 1 by James Charlesworth (@jcharlesworthuk) on CodePen.
Это CSS-правило применяет синюю рамку вокруг любого тега <article>
, содержащего элемент <img>
, визуально отличая статьи с изображениями от статей без них.
Пример 2. Стилизация меню навигации с подменю
Вот еще один пример. В этом примере селектор :has() используется для добавления псевдоэлемента :before()
к любому пункту меню, имеющему подменю — то есть к любому элементу <li>
, содержащему дочерний элемент с классом .sub-menu
.
.main-menu > li:has(.sub-menu):before { content: "▼"; margin-left: 5px; font-size: 0.75em; }
See the Pen Has Selector in CSS — Example 2 by James Charlesworth (@jcharlesworthuk) on CodePen.
От редакции Techrocks: также рекомендуем обратить внимание на статью «Руководство по продвинутым CSS-селекторам».
Поддержка браузеров
По состоянию на март 2024 года селектор :has() поддерживается примерно 92 % браузеров по всему миру, включая все наиболее распространенные современные браузеры, такие как последние версии Chrome, Firefox, Safari и Edge. Для неподдерживаемых браузеров используйте библиотеки обнаружения фич, такие как Modernizr, чтобы применять альтернативные стили.
Также стоит разработать изящный дизайн CSS, чтобы ваши веб-страницы оставались как минимум функциональными и визуально приемлемыми в браузерах, не поддерживающих селектор :has().
:has() готов к использованию уже сегодня
Селектор :has() предлагает новый уровень гибкости и возможностей в CSS, позволяя писать более чистые и эффективные таблицы стилей. Выбирая элементы на основе их содержимого, селектор :has() упрощает многие распространенные задачи стилизации, от выделения статей с изображениями до стилизации отзывчивых макетов.
Поскольку поддержка браузеров продолжает расти, 2024 год — идеальное время, чтобы начать внедрять селектор :has() в свой CSS.
Перевод статьи «How to Use the :has() Selector in CSS».
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]
Это всё здорово, хорошо и интересно. Вот только смысл в этом всём каков? Ведь в :has() явно просматривается необходимость динамичности его применения, что нереализуемо в статичной среде css