Коротко: обратиться к родительскому элементу в CSS долго было нельзя — каскад «идёт» от родителя к потомку. Но сейчас есть селектор :has(), который позволяет выбрать родителя по его потомку. Дополнительно используют :focus-within, :is(), :where() и комбинаторы — а в сложных случаях JavaScript.
Что можно и как
| Задача | Инструмент |
|---|---|
| Родитель по потомку | :has() |
| Родитель при фокусе внутри | :focus-within |
| Разные состояния одного родителя | :is(), :where() |
| Прямой родитель в разметке | комбинатор > (в HTML-разметке, не в CSS) |
Вкладки: способы с кодом
Селектор :has() выбирает элемент, у которого есть нужный потомок:
/* подсветить карточку, если внутри выбрана радиокнопка */
.card:has(input:checked) {
border-color: #003F8F;
box-shadow: 0 0 0 3px rgba(0,63,143,.15);
}Также убирают «крайние» отступы, если внутри картинка:
figure:has(img) { margin: 0; }Поддержка есть в современных браузерах; в совсем старых селектор не сработает — стиль просто не применится (это безопасно).
.field:focus-within {
border-color: #003F8F;
}Стилизует обёртку, когда любое поле внутри получило фокус. Удобно для «рамка вокруг группы полей».
:is(h1, h2, h3).section { margin-bottom: 16px; }
:where(.card, .tile) { border-radius: 8px; }:is() и :where() — не про родителя, а про «группировку» селекторов. :where() имеет нулевую специфичность — удобно, чтобы легко переопределять.
Когда CSS-путей нет (нужны старые браузеры или сложная логика):
const input = document.querySelector('.card input');
if (input.checked) {
input.closest('.card').classList.add('is-selected');
}closest() находит ближайшего родителя по селектору. Дальше стилизуют класс .is-selected.
Практика: карточка выбора тарифа
- Разметьте карточки с радиокнопкой внутри.
- Стилизуйте выбор:
.plan:has(input:checked). - Добавьте рамку/тень для выбранного варианта.
- Проверьте работу с клавиатуры (стрелками).
- Если нужна поддержка старых браузеров — добавьте дублирующий класс через JS.
Частые ошибки: причина → решение
| Симптом | Причина | Решение |
|---|---|---|
:has() не работает |
старый браузер | добавить класс через JS |
| Стиль «не тот» | специфичность :is() выше |
использовать :where() |
| Фокус не подсвечивает обёртку | не задан :focus-within |
добавить правило |
| Тормозит на списке | тяжёлый :has() |
перенести логику в JS/класс |
Проверьте себя
Вопросы и ответы
Только через :has(). Классический «родительский селектор» в CSS не существует — стили идут вниз по дереву.
Селектор, который срабатывает у элемента, если фокус находится у него самого или у любого потомка. Идеален для обёрток форм.
Да, в современных браузерах. В старых селектор просто игнорируется, стили не «ломаются». Для критичных случаев подстрахуйтесь классом.
Проще добавить класс на сервере в шаблоне или через фильтр, чем полагаться на :has() — так надёжнее и быстрее.
Итоги
- CSS идёт от родителя к потомку; «вверх» — только через
:has(). :focus-within— фокус внутри элемента.:is()и:where()— группировка, у второго нулевая специфичность.- Сложные случаи — класс через JavaScript и
closest().
Комментарии
Пока комментариев нет — будьте первым, кто поделится мнением.