Container Queries: The End of Media Queries?
Привет! Присаживайся, наливай кофе. Сегодня обсудим тему, от которой у верстальщиков старой закалки до сих пор пробегает дрожь по спине, а у современных фронтендеров загораются глаза. Речь пойдет о Container Queries (контейнерных запросах).
Давай честно: компонентный подход победил уже давно. Мы пишем интерфейсы на React, Vue, Angular или веб-компонентах. Мы создаем независимые кирпичики: карточки, кнопки, сайдбары, формы. Но до недавнего времени у нас оставалась одна огромная, ноющая боль. Наш дизайн зависел от размеров экрана (Viewport), а не от размеров того места, куда мы этот кирпичик вставляем. И это заставляло нас плодить тонны костылей. Но в 2026 году всё изменилось.
Как мы страдали раньше
Представь классическую задачу: у тебя есть компонент карточки товара. Она должна отлично выглядеть в трех местах: в узком сайдбаре, в сетке каталога (3 колонки) и в промо-баннере во всю ширину экрана.
Если использовать классические Media Queries, карточка знает только ширину экрана смартфона или десктопа. Но она понятия не имеет, что на десктопе ее засунули в узкий сайдбар! Из-за этого нам приходилось выкручиваться:
- Плодить миллион модификаторов в CSS: мы писали тонны классов вроде
.card--sidebar,.card--grid,.card--fullwidth. В итоге стили разрастались до неприличных размеров. - Притягивать за уши JavaScript: мы вешали
ResizeObserverна родительские элементы, динамически мерили их ширину и вешали классы адаптивности. Привет, лишний JS-код на ровном месте, просадка производительности, мигание интерфейса (Layout Shift) и куча багов при рендеринге.
Мы подробно разбирали эти боли и эволюцию подходов в нашей предыдущей статье о проблемах адаптивной верстки, но сейчас пришло время двигаться дальше.
Как делать правильно в 2026 году
Забудь про высчитывание пикселей экрана. Теперь компонент сам решает, как ему выглядеть, исходя из размеров своего родительского контейнера. И для этого не нужен JS. Всё делает чистый CSS.
Процесс состоит из двух простых шагов:
- Шаг 1. Мы объявляем родительский элемент контейнером с помощью свойства
container-type: inline-size(или простоsize, если важна и высота). Так мы говорим браузеру: «Эй, следи за шириной этого парня!». - Шаг 2. Внутри стилей дочернего элемента мы пишем директиву
@containerвместо привычной@media.
Кстати, если тебе интересно, как правильно комбинировать эти подходы в реальных проектах, рекомендуем заглянуть в этот практический разбор контейнерных запросов.
Готовый сниппет кода
Давай посмотрим на лаконичный и рабочий пример. Мы создадим карточку, которая автоматически перестраивается из вертикальной в горизонтальную, как только ее родитель становится шире 500 пикселей.
/* 1. Задаем контекст контейнера для родителя */
.card-wrapper {
container-type: inline-size;
container-name: card-container;
width: 100%;
}
/* 2. Базовые стили карточки (для узкого контейнера) */
.product-card {
display: flex;
flex-direction: column;
gap: 16px;
padding: 16px;
background-color: #f9f9f9;
border-radius: 12px;
border: 1px solid #e0e0e0;
}
.product-card__image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 8px;
}
.product-card__title {
font-size: 1.2rem;
margin: 0;
color: #333;
}
/* 3. Магия Container Queries */
@container card-container (min-width: 500px) {
.product-card {
flex-direction: row;
align-items: center;
gap: 24px;
}
.product-card__image {
width: 150px;
height: 150px;
aspect-ratio: 1 / 1;
}
}
Частая ошибка новичков
Самый жесткий капкан, в который попадают почти все, кто только начинает работать с Container Queries — это попытка изменить стили самого контейнера внутри его же запроса. Это называется Layout Loop (бесконечный цикл разметки).
Представь: ты пишешь, что если ширина контейнера больше 500px, то его собственная ширина должна уменьшиться до 400px. Браузер уменьшает его до 400px, условие перестает выполняться, контейнер снова расширяется до 500px, условие опять выполняется… Браузер сходит с ума, вентиляторы на твоем макбуке начинают взлетать.
Запомни золотое правило: свойство container-type вешается на внешнюю обертку (родителя), а стили через @container мы меняем ТОЛЬКО у внутренних элементов (детей). Сам родительский контейнер внутри своего @container менять нельзя!
Так что, убили ли Container Queries старые добрые Media Queries? Нет, они отлично работают в синергии. Медиа-запросы мы оставляем для глобальной раскладки (сетка сайта, шапка, футер, отступы страницы), а контейнерные запросы отдаем на растерзание изолированным UI-компонентам.
🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!