Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Контейнерные запросы

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

Контейнер

Сначала родителя объявляют контейнером — блоком, размеры которого можно проверять. Для этого служит свойство container-type: inline-size. Inline-size — это размер вдоль строки, то есть для обычного текста ширина:

.wrapper {
  container-type: inline-size;
}

Сам по себе контейнер ничего не меняет внешне. Он только разрешает потомкам задавать вопросы о его ширине.

Правило @container

Правило @container похоже на @media, но условие проверяет ширину ближайшего контейнера. Ниже одна и та же карточка стоит в двух контейнерах разной ширины:

<style>
  .wrapper { container-type: inline-size; margin-bottom: 8px; border: 1px dashed gray; }
  .narrow { width: 220px; }
  .wide { width: 440px; }
  .card { display: grid; gap: 8px; padding: 8px; background: lavender; }
  .pic { height: 60px; background: mediumpurple; }
 
  @container (min-width: 300px) {
    .card { grid-template-columns: 100px 1fr; }
  }
</style>
 
<div class="wrapper narrow">
  <div class="card"><div class="pic"></div><p>Картинка над текстом</p></div>
</div>
<div class="wrapper wide">
  <div class="card"><div class="pic"></div><p>Картинка слева от текста</p></div>
</div>

Код карточки одинаковый, а вид разный: в узком контейнере условие не выполнилось, в широком — выполнилось.

Потяните за угол

Чтобы увидеть переключение вживую, контейнеру можно разрешить менять ширину мышью — свойство resize: horizontal. Потяните за правый нижний угол рамки:

<style>
  .wrapper { container-type: inline-size; resize: horizontal; overflow: hidden; width: 240px; max-width: 100%; border: 1px dashed gray; }
  .card { padding: 12px; background: honeydew; }
 
  @container (min-width: 360px) {
    .card { background: gold; font-size: 20px; }
  }
</style>
 
<div class="wrapper">
  <div class="card">Растяните рамку шире 360 пикселей</div>
</div>

Окно браузера не меняется, а карточка перестраивается.

Имена контейнеров

Если контейнеры вложены друг в друга, @container смотрит на ближайший. Чтобы обратиться к конкретному, ему дают имя через container-name. Короткая запись container задаёт имя и тип сразу:

.sidebar {
  container: sidebar / inline-size;
}
 
@container sidebar (max-width: 250px) {
  .menu { font-size: 14px; }
}

Единицы контейнера

Внутри контейнера работают особые единицы. cqi — один процент от ширины контейнера, как vw для окна:

<style>
  .wrapper { container-type: inline-size; width: 60%; border: 1px dashed gray; }
  .title { font-size: 10cqi; margin: 0; }
</style>
 
<div class="wrapper">
  <p class="title">10cqi</p>
</div>

Шрифт равен десятой части ширины рамки и растёт вместе с ней.

Частая ошибка

Элемент не может проверять собственную ширину: условие @container смотрит на предка. Если объявить контейнером саму карточку, её стили внутри запроса не применятся:

<style>
  .card { container-type: inline-size; padding: 12px; background: mistyrose; }
 
  @container (min-width: 100px) {
    .card { background: gold; }
  }
</style>
 
<div class="card">Я контейнер, но не могу менять себя</div>

Карточка осталась розовой. Объявляйте контейнером обёртку, а стили запроса пишите для того, что внутри.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.