Container queries (контейнерные запросы) позволяют управлять стилем элементов внутри родительского контейнера, а не только через глобальные медиа-запросы. Это решает задачу адаптации виджетов в разных колонках: элемент может менять размер и расположение в зависимости от ширины своего родителя, будь то узкая колонка в сетке или широкий блок.

1. Подготовка структуры и выбор подхода

Прежде чем писать код, определите, какой виджет вы адаптируете. Это может быть блок с карточками товаров, список услуг или форма обратной связи.

Проверьте текущую структуру HTML. Убедитесь, что у родительского блока есть уникальный класс (например, .widget-grid).

Оцените ограничения: контейнерные запросы поддерживаются современными браузерами (Chrome 123+, Safari 17+). Если нужно поддерживать старые браузеры, используйте фоллбэк через @media или CSS-переменные.

Учтите коммерческую задачу: виджет должен быть функциональным в любой колонке. Не жертвуйте удобством ради экспериментов с дизайном.

2. Настройка контейнера и базовых стилей

Добавьте свойство container: inline; или container: inline-size; к родительскому элементу в CSS.

Пример:

.widget-grid {
display: grid;
container-type: inline-size;
gap: 20px;
}

Здесь container-type: inline-size; означает, что ширина контейнера определяется шириной контента внутри него, а не отступами. Это важно для точных расчётов.

Если используется flexbox, добавьте container-type: inline-size; к родителю flex-контейнера.

3. Применение стилей через @container

Используйте псевдокласс @container внутри селектора родителя.

Пример для виджета с карточками:

.widget-grid {
container-type: inline-size;
}

.widget-grid > .card {
/* Базовые стили */
width: 100%;
padding: 16px;
}

@container (min-width: 400px) {
.widget-grid > .card {
width: calc(50% — 10px);
margin-bottom: 0;
}
}

В этом примере карточки занимают всю ширину в узких колонках (<400px), а при достижении 400px делятся на две колонки.

Можно использовать @container (min-width: 600px) для трёхколоночной сетки.

4. Работа с вложенными контейнерами

Если виджет содержит несколько уровней иерархии, применяйте @container на каждом уровне.

Пример:

.outer-widget {
container-type: inline-size;
}

@container (min-width: 800px) {
.inner-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
}

Это позволяет создавать сложные адаптивные структуры без использования @media.

Ограничение: вложенные контейнеры работают только если родительский элемент имеет container-type.

5. Оценка результата и тестирование

Проверьте виджет в разных браузерах: Chrome, Safari, Firefox (с флагом поддержки).

Используйте инструменты разработчика для изменения ширины контейнера вручную.

Убедитесь, что функциональность виджета не нарушается при смене размера колонки.

Проверьте производительность: избыточное использование @container может увеличить размер CSS-файла.

6. Ошибки и ограничения

Ошибка 1: Забыли добавить container-type. Без этого свойства @container не сработает.

Ошибка 2: Использование @container в элементах без display: block/flex/grid. Контейнерные запросы работают только для блочных элементов.

Ограничение: Некоторые браузеры пока не поддерживают контейнерные запросы. Добавьте фоллбэк через @media для старых версий.

Ошибка 3: Неправильный расчёт отступов. Если у контейнера есть padding, он влияет на ширину контента внутри.

7. Практический пример с виджетом услуг

Условный пример: виджет с тремя карточками услуг.

В узкой колонке (до 600px) карточки выстраиваются в одну колонку.

При ширине от 600px до 1200px — две колонки.

При ширине более 1200px — три колонки.

Код:

.services-widget {
container-type: inline-size;
}

.services-widget > .service-card {
width: 100%;
margin-bottom: 20px;
}

@container (min-width: 600px) {
.services-widget > .service-card {
width: calc(50% — 10px);
margin-bottom: 0;
}
}

@container (min-width: 1200px) {
.services-widget > .service-card {
width: calc(33.333% — 6.666px);
margin-bottom: 0;
}
}

Этот подход позволяет одному и тому же контенту корректно отображаться в разных колонках без дублирования кода.

Вопросы и ответы

Можно ли использовать container queries вместе с @media?

Да, это распространённая практика. @container отвечает за адаптацию внутри компонента, а @media — за глобальную адаптацию страницы.

Как проверить поддержку контейнерных запросов в браузере?

Используйте CSS-свойство container-type: inline-size; и проверьте, применяются ли стили внутри @container. В старых браузерах они будут игнорироваться.

Нужно ли переписывать весь код с @media на @container?

Нет. Используйте @container там, где это уместно (локальная адаптация), а @media оставьте для глобальных изменений.

.widget-grid {
  display: grid;
  container-type: inline-size;
  gap: 20px;
}

.widget-grid > .card {
  width: 100%;
  padding: 16px;
}

@container (min-width: 400px) {
  .widget-grid > .card {
    width: calc(50% - 10px);
    margin-bottom: 0;
  }
}