Клавиша / esc

@container

Контейнерные запросы: применяем стили по размерам ближайшего контейнера, а не окна браузера.

Время чтения: меньше 5 мин

Кратко

Скопировано

Директива @container включает «контейнерные запросы» — условные правила, которые зависят от размеров (и стилей) ближайшего контейнера, а не от размеров вьюпорта. Это делает компоненты по‑настоящему адаптивными и независимыми от общего макета.

Пример

Скопировано
        
          
          <div class="cards" aria-label="Список карточек">  <article class="card">Карточка 1</article>  <article class="card">Карточка 2</article>  <article class="card">Карточка 3</article>  <article class="card">Карточка 4</article>  <article class="card">Карточка 5</article></div>
          <div class="cards" aria-label="Список карточек">
  <article class="card">Карточка 1</article>
  <article class="card">Карточка 2</article>
  <article class="card">Карточка 3</article>
  <article class="card">Карточка 4</article>
  <article class="card">Карточка 5</article>
</div>

        
        
          
        
      
        
          
          /* Объявляем контейнер: измеряем его inline‑ось (ширину в LTR/RTL) */.cards {  container-type: inline-size;  display: grid;  gap: 12px;  grid-template-columns: repeat(3, 1fr);}/* Когда контейнер сужается, меняем компоновку — компонент адаптируется сам по себе */@container (max-width: 600px) {  .cards { grid-template-columns: repeat(2, 1fr); }}@container (max-width: 380px) {  .cards { grid-template-columns: 1fr; }}
          /* Объявляем контейнер: измеряем его inline‑ось (ширину в LTR/RTL) */
.cards {
  container-type: inline-size;
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(3, 1fr);
}

/* Когда контейнер сужается, меняем компоновку — компонент адаптируется сам по себе */
@container (max-width: 600px) {
  .cards { grid-template-columns: repeat(2, 1fr); }
}

@container (max-width: 380px) {
  .cards { grid-template-columns: 1fr; }
}

        
        
          
        
      
Открыть демо в новой вкладке

Как пишется

Скопировано

Контейнерный запрос срабатывает только в пределах контейнера. Чтобы он заработал, нужно:

  1. Объявить контейнер на элементе‑родителе компонентов.
        
          
          .wrapper {  container-type: inline-size; /* измерять только inline‑размер */  /* или */  /* container-type: size; измерять и inline, и block размеры */}
          .wrapper {
  container-type: inline-size; /* измерять только inline‑размер */
  /* или */
  /* container-type: size; измерять и inline, и block размеры */
}

        
        
          
        
      
  1. По желанию дать контейнеру имя и ссылаться на него в @container:
        
          
          .wrapper { container-name: layout; container-type: inline-size; }@container layout (min-width: 700px) {  /* правила для компонентов внутри .wrapper */}
          .wrapper { container-name: layout; container-type: inline-size; }

@container layout (min-width: 700px) {
  /* правила для компонентов внутри .wrapper */
}

        
        
          
        
      
  1. Писать условия как в @media, но измеряется именно контейнер:
        
          
          @container (min-width: 480px) { /* ... */ }@container (width > 30rem) { /* диапазонный синтаксис */ }@container style(--ui: compact) { /* стилевые запросы по вычисленным стилям */ }
          @container (min-width: 480px) { /* ... */ }
@container (width > 30rem) { /* диапазонный синтаксис */ }
@container style(--ui: compact) { /* стилевые запросы по вычисленным стилям */ }

        
        
          
        
      

Поддерживаются типы контейнеров:

  • inline-size — учитывает только ширину по inline‑оси;
  • size — учитывает и ширину, и высоту;
  • normal — отключает контейнер.

Важно: контейнер не может участвовать в размерах своих потомков, от которых он сам зависит (цикл измерений). Обычно достаточно задать «изоляцию» размеров через блок‑контекст форматирования (например, display: grid | flow-root | flex) или явно управлять размерами.

Как понять

Скопировано

@container решает классическую проблему адаптивности компонентов: ваш виджет может жить в сайдбаре и в контентной колонке, а меняться он должен по ширине своего родителя, а не окна. Теперь «точки перелома» описываются около компонента и работают в любом контексте вёрстки.

Контейнерные запросы дополняют, но не заменяют @media: первые — про локальную компоновку, вторые — про глобальную.

Подсказки

Скопировано

💡 Всегда объявляйте контейнер на ближайшем родителе компонента (container-type). Без этого @container не сработает.
💡 Используйте имена контейнеров (container-name), когда на странице несколько контейнеров и правила не должны пересекаться.
💡 Храните брейкпоинты рядом с компонентом — так проще сопровождать дизайн‑систему.
💡 Для производительности избегайте слишком глубоких деревьев с множеством контейнеров без необходимости.

Поддержка в браузерах:
  • Chrome 105, поддерживается
  • Edge 105, поддерживается
  • Firefox 110, поддерживается
  • Safari 16, поддерживается
О Baseline