Container Queries: The End of Media Queries?

Container Queries: The End of Media Queries?

Присаживайся, наливай кофе. Сегодня разберем тему, которая прямо сейчас меняет правила игры в адаптивной верстке. Если ты до сих пор верстаешь компоненты, оглядываясь исключительно на ширину экрана девайса, у меня для тебя плохие новости: ты застрял в прошлом десятилетии. Но хорошая новость в том, что мы это сейчас исправим.

Представь классическую боль: ты написал шикарную карточку товара. В сетке на всю ширину она выглядит идеально, в три колонки — сносно. Но стоит засунуть ее в узкий сайдбар — и всё едет к чертям. Текст слипается, кнопка вылезает за границы, картинка сжимается в пиксельную кашу. Знакомо? Давай разберем, как мы решали это раньше и как элегантно закрыть этот вопрос раз и навсегда.

Как мы страдали раньше

До появления современных CSS-свойств у нас был только один инструмент — Media Queries. И это был сплошной костыльный театр. Нам приходилось плодить десятки сущностей, чтобы один и тот же компонент адекватно смотрелся в разных частях сайта. Как мы выкручивались?

  • Миллион модификаторов. Мы писали тонны классов: .card--sidebar, .card--hero, .card--grid-3-col. Стоило дизайнеру перетащить карточку в другое место, и приходилось переписывать стили в CSS.
  • JS-костыли. Использовали ResizeObserver в JavaScript, чтобы отслеживать размеры конкретного DOM-элемента и навешивать классы на лету. Привет, Layout Thrashing, просадка FPS и дерганая анимация при изменении размера окна!
  • Привязка к вьюпорту. Мы пытались угадать поведение компонента, зная лишь ширину экрана телефона или десктопа. Но ведь карточке в сайдбаре плевать, открыт сайт на мониторе 4K или на iPhone. Ей важны только те 300 пикселей, которые выделил под нее сайдбар.

Как мы уже упоминали в первой части нашего разбора Container Queries, медиа-запросы изначально создавались для макро-разметки страниц, а не для микро-адаптива независимых компонентов. Пытаться верстать ими сложные интерфейсы — это как забивать гвозди микроскопом.

Как делать правильно в 2026 году

Сегодня Container Queries (контейнерные запросы) стали полноценным стандартом, который поддерживается всеми современными браузерами. Идея проста до гениальности: мы говорим элементу реагировать не на ширину экрана (viewport), а на ширину его непосредственного родителя (контейнера).

Теперь наш компонент становится по-настоящему изолированным. Мы можем закинуть его в сайдбар, в подвал, в модалку или в сложную сетку Grid — он сам поймет, сколько у него свободного места, и перестроится под него. Кстати, для сложных раскладок внутри карточки идеально зайдет связка с Subgrid — подробнее об этом читай в нашем полном руководстве по CSS Grid Subgrid.

Чтобы магия заработала, нам нужно сделать всего два шага:

  • Объявить родительский элемент контейнером с помощью свойства container-type.
  • Написать стили для дочернего элемента внутри правила @container вместо привычного @media.

Готовый сниппет кода

Давай закодим адаптивную карточку, которая легким движением руки превращается из горизонтальной в вертикальную, как только ей становится тесно. Обрати внимание, как изящно это работает без единой строчки на JS и без медиа-запросов.

<!-- HTML-разметка -->
<div class="card-wrapper">
  <article class="product-card">
    <img src="product.jpg" alt="Product" class="product-card__img">
    <div class="product-card__content">
      <h3 class="product-card__title">Крутой девайс</h3>
      <p class="product-card__desc">Этот девайс изменит твою жизнь раз и навсегда.</p>
      <button class="product-card__btn">Купить</button>
    </div>
  </article>
</div>

<!-- CSS-стили -->
<style>
/* 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: #f5f5f7;
  border-radius: 12px;
}

.product-card__img {
  width: 100%;
  height: auto;
  aspect-ratio: 16/9;
  object-fit: cover;
  border-radius: 8px;
}

/* 3. Магия: если контейнер шире 500px, делаем карточку горизонтальной */
@container card-container (min-width: 500px) {
  .product-card {
    flex-direction: row;
    align-items: center;
  }

  .product-card__img {
    width: 180px;
    aspect-ratio: 1/1;
  }
}
</style>

Частая ошибка новичков

Главный капкан, в который стабильно попадают мидлы при первом знакомстве с контейнерами — это попытка повесить container-type и сам запрос @container на один и тот же элемент.

Запомни железобетонное правило: компонент не может опрашивать сам себя. Если ты напишешь:

.product-card {
  container-type: inline-size;
}

@container (min-width: 500px) {
  .product-card {
    /* ТАК НЕ РАБОТАЕТ! */
  }
}

Браузер просто проигнорирует эти стили. Почему? Потому что изменение стилей элемента внутри медиа-запроса может изменить его собственный размер, что вызовет бесконечный цикл перерендеринга (свойство меняет размер -> размер меняет стили -> стили меняют размер). Браузеры умные, они пресекают это на корню. Контейнером всегда должен быть родительский элемент (обертка), а стилизовать мы должны его потомков.

Убивают ли Container Queries медиа-запросы окончательно? Нет. Media Queries всё еще идеальны для глобальной сетки страницы, темизации (dark mode) и системных настроек пользователя. Но для верстки независимых компонентов контейнеры — это безоговорочный стандарт современной веб-разработки.

🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!

🚀 Прокачай свой код

Готовые CSS-сниппеты, разбор продвинутых фишек и эксклюзивные материалы — в нашем Telegram-канале.

Подписаться
error: Content is protected !!
Прокрутить вверх