HTML/CSSMiddleTechnical

Что такое CSS container queries и чем они отличаются от media queries?

Media queries реагируют на ширину viewport. Container queries — на ширину ближайшего контейнера. Это позволяет компоненту адаптироваться независимо от того, где в макете он находится.

В чём проблема media queries

Media query привязана к размеру viewport. Если карточка в сайдбаре (300 px) и в главной колонке (800 px) должны выглядеть по-разному, media query не поможет — она не знает, насколько широк родительский контейнер. Приходилось передавать CSS-классы через JS или использовать ResizeObserver — оба варианта хрупкие.

Как работают container queries

Элемент-контейнер помечается свойством container-type. Браузер начинает отслеживать его размер. Дочерние элементы могут запрашивать этот размер через @container.

/* 1. Объявляем контейнер */
.card-wrapper {
  container-type: inline-size; /* отслеживать ширину */
  container-name: card;        /* опционально — имя */
}

/* 2. Стили для дочернего элемента в зависимости от ширины контейнера */
@container (min-width: 480px) {
  .card {
    display: grid;
    grid-template-columns: 160px 1fr;
    gap: 16px;
  }
}

@container (max-width: 479px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}
<!-- Сайдбар: контейнер узкий → вертикальная карточка -->
<aside class="card-wrapper">
  <div class="card">...</div>
</aside>

<!-- Главная колонка: контейнер широкий → горизонтальная карточка -->
<main class="card-wrapper">
  <div class="card">...</div>
</main>

Один и тот же CSS-компонент автоматически адаптируется — без дополнительных классов или JavaScript.

container-type: size vs inline-size

  • inline-size — отслеживает только ширину. Используется в 99% случаев.
  • size — отслеживает ширину и высоту. Требует, чтобы у контейнера была явная высота, иначе браузер не может её измерить (intrinsic height становится 0).
  • normal — контейнер для style queries, но не для size queries.

Style queries

Помимо размеров, можно делать запросы по значениям CSS-custom-properties контейнера:

@container style(--variant: compact) {
  .card__image { display: none; }
}

Style queries поддерживаются в Chrome 111+ / Safari 18+, но пока не в Firefox (статус: в разработке).

Подводные камни

  • Элемент не может запрашивать собственный контейнер. Контейнер создаёт новый контекст форматирования: элемент с container-type не может сам участвовать в @container запросе, который он определяет. Правило всегда применяется к потомкам.
  • container-type: size ломает intrinsic height. При size браузер изолирует контейнер по обеим осям — его высота не определяется содержимым. Если не задать явную высоту, контейнер схлопнется в 0.
  • Производительность при вложенных контейнерах. Каждый уровень container-type добавляет работу браузеру для отслеживания размеров. В длинных списках с контейнерами на каждой карточке это заметно при resize — лучше ставить контейнер как можно выше в дереве.
  • Нет медиа-условий о типе устройства. Container queries не заменяют media queries полностью: @media (prefers-color-scheme: dark), @media print, ориентация — это всё viewport/device-level условия. Оба инструмента нужны вместе.
  • Именование контейнеров — глобальное. container-name не имеет scope. Одинаковые имена в разных компонентах конкурируют, а @container card найдёт ближайшего предка с именем card — не обязательно ожидаемый.
  • Поддержка браузеров. Базовые size container queries поддерживаются с Chrome 105, Safari 16, Firefox 110 (2023). Если нужно поддерживать браузеры до 2023 года — необходим полифилл (container-query-polyfill) или fallback через media queries.
  • Инструменты разработчика. DevTools в Chrome/Firefox 2024 показывают контейнеры в Elements-панели, но подсветка не всегда очевидна. При отладке удобно временно добавить outline: 2px solid red на элемент с container-type, чтобы увидеть реальную ширину контейнера.

Common mistakes

  • Смешивать «container queries» с похожим механизмом без критерия выбора.
  • Игнорировать риск: неверно оценить границы применения темы «container queries» и получить хрупкое решение.
  • Показывать только синтаксис и не объяснять поведение в runtime или сборке.

What the interviewer is testing

  • Объясняет адаптация компонента по размеру контейнера, а не только viewport.
  • Показывает на примере, как работает: container query работает от query container и позволяет компоненту менять layout в sidebar, card grid или narrow panel без знания общей ширины страницы.
  • Называет production-нюанс и граничный случай для темы «container queries».

Sources

Related topics