CSS Container Query: Новый шаг в адаптивность и независимость блоков страницы

CSS Container Query example

Новый функционал, который уже имеет широкую поддержку браузеров и позволяет делать html модули максимально независимыми от остальной страницы. Вы можете задавать поведение внутренних элементов основываясь только на запросы о параметрах контейнерного блока.

В целом @container запросы работают так же, как @media запросы, только не к странице, а к определенному особым способом родительскому блоку.

Достаточно указать блоку свойство container-type (size, inline-size, or normal) и он становится контейнером. Так же можно задать ему имя, для уточнения запросов.

.post {
  container-type: inline-size;
  container-name: sidebar;
}

Базовый синтаксис

Основываясь на mdn, получаем такой синтаксис запроса:

@container <container-condition># {
  <stylesheet>
}

/* Пример: */
/* multiple queries in a single condition */
@container (width > 400px) and style(--responsive: true) {
  h2 {
    font-size: 1.5em;
  }
}

Самое интересное тут, что мы можем делать запросы не только о ширине, высоте. Функционал намного шире, мы можем описаться на стили и даже на определенные переменные! Те фактически можем управлять внутренним поведением блока, переопределяя CSS переменные в зависимости от необходимости например.

Новые единицы изменения

Для определения высоты и ширины относительно контейнера появились новые размерности:

  • cqw: 1% ширины контейенра;
  • cqh: 1% высоты контейнера;
  • cqi: 1% inline размер контейнера;
  • cqb: 1% block размер контейнера;
  • cqmin: меньшее из cqi or cqb;
  • cqmax: большее из cqi or cqb.

Пример

В приведенном примере мы постарались раскрыть базовый вариант использования контейнерных запросов на базе поведения блока .item, который опираясь на ширину и переменную, определяемую для одного из родителей, меняет свое поведение. Однако style() работает еще не во всех браузерах, проверяйте совместимость перед использованием в реальных задачах. (работает в Chrome)

  .testWrapper {
    display: flex;
    flex-flow: row wrap;
    gap: 5px;
  }
  .items {
    container-type: inline-size;
    border: 1px solid black;
    display: flex;
    flex-flow: row wrap;
    justify-content: space-between;
    gap: 5px;
    margin: 10px;
  }
  .items1 {
    width: 300px;
  }
  .items2 {
    width: 200px;
  }
  .items3 {
    width: 100px;
  }

  .thumbnail {
    background-color: rgb(96, 195, 108);
  }
  .text {
    background-color: rgb(237, 57, 87);
  }
  .header {
    background-color: rgb(11, 179, 235);
  }

  .item {
    width: 100%;
    background-color: rgb(54, 54, 54);
    display: grid;
    gap: 5px;
  }

  .item__var2 {
    --variant2: true;
  }

  .item div {
    min-width: 25px;
    min-height: 25px;
  }

  .item div:last-child {
    display: none;
  }

  @container (width > 100px) and (width < 201px) {
    .item {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
      width: calc(50cqi - 2.5px);
    }
    .item div:last-child {
      grid-column: 1 / span 2;
      display: block;
    }
  }

  @container (width > 100px) and (width < 201px) and style(--variant2: true) {
    .item div:last-child {
      grid-row: 1 / span 2;
      grid-column: 1;
      display: block;
    }
  }

  @container (width > 200px) {
    .item {
      display: grid;
      grid-template-columns: 1fr;
      gap: 10px;
      width: 20cqi;
    }
    .item div:last-child {
      display: block;
    }
  }
<div class="testWrapper">
  <div class="items items1">
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
  </div>
  <div class="items items2">
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
  </div>
  <div class="items items2 item__var2">
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
  </div>
  <div class="items items3">
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
    <div class="item">
      <div class="thumbnail"></div>
      <div class="header"></div>
      <div class="text"></div>
    </div>
  </div>
</div>

Итого

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

Comments are closed, but trackbacks and pingbacks are open.