CSS: Введение в контейнерные запросы
Контейнерные запросы позволяют стилизовать элементы в зависимости от доступного пространства. Они позволяют создавать устойчивые компоненты, которые можно адаптировать к бесконечному количеству неизвестных компоновок. Это отличается от медиа-запросов области просмотра, которые требуют, чтобы изменения стиля были согласованы на уровне страницы.
Контейнерные запросы vs Медиа-запросы области просмотра
Скорее всего, вы знакомы с отзывчивым дизайном и макетами, реагирующими на область просмотра, как показано на рисунке ниже.
В отзывчивом дизайне области просмотра популярно связывать макетную сетка с контрольными точками. Эти контрольные точки обычно связаны с упрощёнными размера устройств, как показано на рисунке выше, такими как мобильные устройства, планшеты и настольные компьютеры.
Важно отметить, что эти точки останова не обязательно учитывают отдельные элементы и компоненты на экране, а больше фокусируются на том, как компоненты перетекают в предопределённую сетку. Иногда более крупные компоненты, такие как навигация, трансформируются отдельно от сетки, но обычно они используют глобальные контрольные точки.
Давайте сравним отзывчивый дизайн области просмотра с отзывчивым дизайном контейнера.
На изображении ниже представлены варианты карточного компонента. Эти варианты визуализируются с использованием контейнерных запросов, которые полностью не зависят от области просмотра. Стили карт настраиваются в зависимости от доступного места.
Примечание: Контейнерные запросы поддерживаются во всех вечнозелёных браузерах, начиная с версии Firefox 110. Чтобы расширить поддержку старых браузеров, доступен полифилл.
Во-первых, давайте изучим синтаксис для создания контейнерных запросов.
Определение контейнерных запросов
Первый шаг — указать, что элемент является контейнером, используя свойство container-type
. Наиболее фундаментальное и в настоящее время лучше всего поддерживаемое значение — inline-size
, которое в режиме горизонтального письма соответствует ширине элемента. Таким образом, это определение означает, что мы намерены поддерживать запрос на основе внутреннего размера элемента .container
:
.container {
container-type: inline-size;
}
Добавление container-type
к элементу официально обозначает его как контейнер.
Далее мы создадим настоящий контейнерный запрос, используя контейнерное at-правило @container
принимающее параметр, который будет выглядеть знакомым, если вы когда-либо назначали медиа-запросы.
Следующее правило @container
гласит, что если <h2>
находится внутри контейнера шириной 40ch
и более, его цвет должен быть blue
:
@container (min-width: 40ch) {
h2 {
color: blue;
}
}
Примечание: Правила, которые мы размещаем в контейнерном запросе, не будут влиять на стиль самого контейнера, а только на его дочерние элементы. Это означает, что мы не можем стилизовать контейнер из его собственного запроса. Но мы можем стилизовать контейнер с запросом контейнера, если у этого контейнера есть предок, который также определён как контейнер.
Чтобы учесть больше, чем горизонтальный режим записи, мы можем обновить наш запрос, чтобы использовать логический синтаксис inline-size
, а не основывать запрос строго на ширине
контейнера:
@container (inline-size > 40ch) {
h2 {
color: blue;
}
}
Есть больше параметров, чем просто inline-size
, включая block-size
и aspect-ratio
. Чтобы узнать больше о доступных контейнерных запросах размера и о том, как их использовать, ознакомьтесь с официальной спецификацией.
Обновление компонента карты
Если бы мы хотели создать компонент карты без контейнерных запросов, мы могли бы создавать варианты с помощью классов модификаторов. А для вариаций размера карты эти модификаторы могут быть привязаны к контрольным точкам. Это означает, что если бы у карты был модификатор, его можно было бы изменить, когда ширина области просмотра попала в это точку останова/breakpoint.
На следующем изображении показаны три варианта размера карты и соответствующие им классы модификаторов, где верхняя .card
будет считаться по умолчанию
.
Вот живая демонстрация CodePen карты, реагирующей на область просмотра, изображённая выше. (Измените размер области просмотра, чтобы увидеть, как работают различные стили)
Теперь давайте сменим перспективу и подумаем, как мы будем обрабатывать эти варианты карт, используя контейнерные запросы.
Мы по-прежнему будем использовать верхнюю карту по умолчанию, что на самом деле означает — она будет применяться при самой узкой ширине. Это также будет резервная версия, где, контейнерные запросы не поддерживаются — важный сценарий, который следует учитывать до тех пор, пока контейнерные запросы не достигнут полной поддержки.
Мы установим макет карты среднего размера (с горизонтальной ориентацией), чтобы он активировался, когда ширина контейнера составляет 350px
или больше.
Наконец, мы настроим макет карты на использование её изображения в качестве фона, когда ширина контейнера составляет 600px
или больше.
Это создаст элемент карты, который может адаптироваться в зависимости от размера контейнеров для карт. Поиграйте со следующей демонстрацией CodePen, чтобы увидеть это в действии. (Обратите внимание на указатель Resize me!
в правом нижнем углу, с его помощью можно изменять размер.)