@container и :has(): два новых мощных адаптивных API, появившихся в Chromium 105.

Контейнерные запросы и :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 и набирают обороты кроссбраузерной поддержки, настало такое захватывающее время для разработчика пользовательского интерфейса!