Эра адаптивности 2.0: Почему Media Queries больше не вывозят?
Присаживайся, наливай кофе. Давай начистоту: сколько раз ты ловил себя на мысли, что адаптивная верстка — это сизифов труд? Ты берешь обычную карточку товара, которая должна идеально смотреться и в боковой панели (шириной 300px), и в трехколоночной сетке, и на всю ширину экрана. Пишешь тонну медиа-запросов, завязанных на ширину экрана (viewport)… И тут дизайнер меняет сетку. Всё летит к чертям, и ты начинаешь переписывать стили заново.
Проблема в том, что обычные медиа-запросы заставляют нас думать масштабами всего экрана. Но компоненту абсолютно плевать на размер экрана смартфона или монитора! Ему важно лишь то, сколько места выделил под него его непосредственный родитель. И вот здесь на сцену выходят Container Queries (контейнерные запросы), которые переворачивают игру с ног на голову.
Как мы страдали раньше (и почему это было больно)
Вспомни, как мы выкручивались еще пару лет назад. У нас было три пути, и все три вели в ад поддержки кода:
- Множественные модификаторы. Мы плодили классы вроде
.card--sidebar,.card--hero,.card--grid. Стоило перенести карточку из одного сайдбара в другой блок, и приходилось лезть в HTML или JS-шаблон и руками менять класс. Никакой автономности. - Костыли на JavaScript. Мы подключали тяжелые
ResizeObserver, отслеживали размеры контейнера программно, дергали стейт компонента и вешали соответствующие классы на лету. Привет, лишний JS в бандле, микро-фризы при ресайзе страницы и вечная головная боль с серверным рендерингом (SSR). - Жесткие рамки сетки. Мы пытались связать все воедино через сложные CSS-сетки. Кстати, если тебе интересна тема гибких раскладок без лишней боли, обязательно почитай статью про Mastering CSS Grid Subgrid — это еще один мощный инструмент, который идеально работает в связке с современными контейнерами.
Как делать правильно в 2026 году: Полная автономность
В 2026 году Container Queries — это уже абсолютный стандарт, поддерживаемый всеми современными браузерами на 100%. Теперь компонент сам решает, как ему выглядеть, исходя из размеров своего родителя. Все, что нам нужно — это объявить родительский элемент «контейнером», а для дочернего написать простые правила.
Если хочешь освежить в памяти базу по этой технологии, загляни в наш подробный разбор Container Queries: The End of Media Queries?, а сейчас давай перейдем к практике и посмотрим, как это выглядит в реальном коде.
Мы используем свойство container-type: inline-size, чтобы сказать браузеру: «Эй, следи за шириной этого элемента!». А затем, вместо привычного @media, мы пишем @container (min-width: ...). Это полностью развязывает нам руки: теперь карточку можно вставить в любое место сайта, и она сама подстроится под окружение.
Готовый сниппет кода: Карточка-хамелеон
Давай посмотрим на живой пример. У нас есть родительский блок-контейнер и карточка внутри него. Обрати внимание, как изящно меняется раскладка без использования JS и глобальных медиа-запросов:
/* 1. Объявляем родительский элемент контекстом контейнера */
.parent-wrapper {
container-type: inline-size;
container-name: card-container; /* Имя контейнера для точечного таргетинга */
width: 100%;
}
/* 2. Базовые стили карточки (для узкого контейнера / mobile-first подход) */
.product-card {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1rem;
background: #f9f9f9;
border-radius: 8px;
}
.product-card img {
width: 100%;
height: auto;
object-fit: cover;
}
/* 3. Адаптируем карточку под ширину РОДИТЕЛЯ, а не экрана! */
@container card-container (min-width: 500px) {
.product-card {
flex-direction: row;
align-items: center;
}
.product-card img {
width: 150px;
height: 150px;
}
}
@container card-container (min-width: 800px) {
.product-card {
padding: 2rem;
background: #eef5ff;
}
.product-card .title {
font-size: 1.8rem;
}
}
Частая ошибка новичков (Осторожно, бесконечный цикл!)
Самая частая грабля, на которую наступают разработчики при первом знакомстве с технологией — это попытка изменить размеры самого контейнера внутри его же запроса. Например:
/* ТАК ДЕЛАТЬ НЕЛЬЗЯ */
@container (min-width: 500px) {
.parent-wrapper {
width: 300px;
}
}
Браузер видит, что ширина больше 500px, применяет стиль, уменьшает ширину контейнера до 300px… Но теперь ширина меньше 500px, стиль отменяется, ширина снова растет. В итоге браузер попадает в бесконечный цикл рендеринга, интерфейс начинает дико мерцать, а процессор улетает в космос.
Вторая ошибка — путать container-type: size и container-type: inline-size. Если ты укажешь просто size, то браузер будет ожидать, что ты зафиксировал и ширину, и высоту контейнера. Если высота не задана жестко, контейнер сожмется в ноль (высота схлопнется). Поэтому в 95% случаев для верстки гибких компонентов тебе нужен именно inline-size.
Убивают ли Container Queries старые добрые Media Queries? Конечно, нет. Глобальную сетку страницы, шапку и подвал мы по-прежнему верстаем через @media. Но вот внутренности компонентов теперь — строго зона ответственности @container. Это и есть настоящий, чистый компонентный подход в CSS.
🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!