Контейнерные запросы и :has() — это соответствие, созданное на небесах отзывчивости. К счастью, обе эти функции появились вместе в Chromium 105. Это масштабный выпуск с двумя востребованными функциями для адаптивных интерфейсов!
Контейнерные запросы: краткое описание
Контейнерные запросы позволяют разработчикам запрашивать у родительского селектора его размер и информацию о стиле, что позволяет дочернему элементу владеть своей адаптивной логикой стиля, независимо от того, где он находится на веб-странице.
Вместо того, чтобы полагаться на область просмотра для стилизации входных данных, таких как доступное пространство, у разработчиков теперь есть возможность запрашивать размер элементов на странице. Эта возможность означает, что компонент владеет своей логикой адаптивного стиля. Это делает компонент гораздо более устойчивым, поскольку к нему прикрепляется логика стиля, независимо от того, где он появляется на странице.
Использование контейнерных запросов
Для построения запросов к контейнеру необходимо сначала установить включение родительского элемента. Сделайте это, установив container-type для родительского контейнера. У вас может быть карточка с изображением и текстовым содержимым, которая выглядит следующим образом:

Чтобы создать запрос к контейнеру, установите container-type для контейнера карты:
.card-container {
container-type: inline-size;
}
Установка container-type в inline-size запрашивает размер родительского элемента в линейном направлении. В латинских языках, таких как английский, это будет ширина карточки, поскольку текст движется по строкам слева направо.
Теперь мы можем использовать этот контейнер для применения стилей к любому из его дочерних элементов с помощью @container :
.card {
display: grid;
grid-template-columns: 1fr 1fr;
}
@container (max-width: 400px) {
.card {
grid-template-columns: 1fr;
}
}
Родительский селектор :has()
Псевдокласс CSS :has() позволяет разработчикам проверять, содержит ли родительский элемент дочерние элементы с определенными параметрами.
Например, p:has(span) указывает на селектор абзаца ( p ), внутри которого находится span . Вы можете использовать это для стилизации самого родительского абзаца или чего-либо внутри него. Одним из полезных примеров является figure:has(figcaption) для стилизации элемента figure , содержащего подпись. Вы можете узнать больше о :has() в этой статье Джей Томпкинса .
Контейнерные запросы и :has()
Вы можете комбинировать возможности родительского выбора :has() с возможностями родительских запросов контейнерных запросов, чтобы создать действительно динамические внутренние стили.
Давайте расширим первый пример с картой-ракетой. Что делать, если у вас есть карта без изображения? Возможно, вы хотите увеличить размер заголовка и настроить макет сетки на один столбец, чтобы он выглядел более продуманно без изображения.

В этом примере карточка с изображением имеет шаблон сетки из двух столбцов, тогда как карточка без изображения имеет макет из одного столбца. Кроме того, карточка без изображения имеет заголовок большего размера. Чтобы написать это с помощью :has() используйте следующий CSS.
.card:has(.visual) {
grid-template-columns: 1fr 1fr;
}
Вам нужен элемент с visual классом, к которому можно применить описанный выше стиль двух столбцов. Еще одна изящная функция CSS — :not() . Это часть той же спецификации, что и :has() , но она существует гораздо дольше и имеет лучшую поддержку браузеров . Вы даже можете комбинировать :has() и :not() , например:
.card:not(:has(.visual)) h1 {
font-size: 4rem;
}
В приведенном выше коде вы пишете селектор, который стилизует h1 внутри карты, не содержащей visual класса. Так вы сможете очень четко настроить размер шрифта.
Собираем все это вместе
В приведенной выше демонстрации показана комбинация :has() , :not() и @container , но контейнерные запросы действительно хороши, когда вы можете видеть один и тот же элемент, используемый в нескольких местах. Давайте добавим немного стиля и покажем эти карточки в сетке рядом друг с другом.
Теперь вы действительно можете увидеть мощь современного CSS. Мы можем писать четкие стили, используя целевые стили, которые строят логику поверх логики и создают действительно надежные компоненты. Благодаря тому, что эти две мощные функции появились в Chromium 105 и набирают обороты кроссбраузерной поддержки, настало такое захватывающее время для разработчика пользовательского интерфейса!