:has селектор
:has— псевдокласс CSS, который выбирает элемент, если внутри него есть элемент, соответствующий переданному селектору; фактически первый «родительский» селектор в CSS.
Зачем нужно
До :has было невозможно стилизовать родительский элемент на основе его содержимого без JavaScript. :has открывает принципиально новые возможности: стилизовать форму если она содержит незаполненные обязательные поля, карточку если в ней есть изображение, параграф если за ним следует другой параграф.
Где используется
- Стилизация родителя по дочернему содержимому
- Формы: подсветка при наличии невалидных полей
- Карточки: разные стили при наличии/отсутствии изображения
- Навигация: выделение активного раздела
- Замена JavaScript для условной стилизации
Синтаксис
/* Выбрать .card если внутри есть img */
.card:has(img) { ... }
/* Выбрать form если внутри есть :invalid */
form:has(:invalid) { ... }
/* Выбрать h2 если за ним идёт p (смежный сосед) */
h2:has(+ p) { ... }
/* Выбрать li если внутри есть a.active */
li:has(a.active) { ... }
/* Комбинирование с другими псевдоклассами */
.card:not(:has(img)) { ... } /* карточки БЕЗ изображения */
Примеры
Карточка с изображением — другой стиль
/* Без изображения */
.card {
padding: 24px;
}
/* С изображением — убрать padding сверху */
.card:has(img) {
padding-top: 0;
}
.card:has(img) img {
border-radius: 8px 8px 0 0;
width: 100%;
}
Форма с невалидными полями
/* Форма ошибки — красная рамка вокруг всей формы */
form:has(:invalid:not(:placeholder-shown)) {
border: 2px solid #e44;
border-radius: 8px;
}
/* Кнопка отправки заблокирована при наличии ошибок */
form:has(:invalid) button[type="submit"] {
opacity: 0.5;
pointer-events: none;
}
<form>
<input type="email" required placeholder="Email">
<button type="submit">Отправить</button>
</form>
Выделение активного пункта меню
/* li активен если внутри есть активная ссылка */
nav li:has(a.active) {
background: rgba(0, 123, 255, 0.1);
border-left: 3px solid #007bff;
}
Сетка без изображения — три колонки; с — две
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.grid:has(.featured-img) {
grid-template-columns: 1fr 2fr; /* два блока если есть featured */
}
Поддержка браузеров
Chrome 105+, Safari 15.4+, Firefox 121+. Проверяйте актуальный статус: caniuse.com/css-has
/* Защита для старых браузеров через @supports */
@supports selector(:has(a)) {
.card:has(img) { padding-top: 0; }
}
Частые ошибки
:hasс комплексными селекторами —:has(.a .b)выбирает элемент у которого есть.bвнутри.aвнутри него — не самый читаемый код; держите аргументы простыми.- Производительность — сложные аргументы
:hasмогут влиять на производительность рендеринга; избегайте:has(*)или очень глубоких вложений. forgivingпарсинг —:hasиспользует «forgiving» список: невалидный аргумент не ломает весь селектор, а игнорируется.
Связанные темы
- _MOC CSS
- Псевдоклассы
- Комбинаторы -- потомок, дочерний, соседний
- Группировка и вложенность селекторов