Несколько раз запросы о размере контейнера помогли бы мне в разведке данных PlatoBlockchain. Вертикальный поиск. Ай.

Несколько случаев, когда мне помогли бы запросы о размере контейнера

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

Хотя они, безусловно, удобны! На самом деле, я уже сталкивался с несколькими ситуациями, когда я действительно хотел получить их, но просто не мог преодолеть требования поддержки. Если бы я мог их использовать, вот как это выглядело бы в тех ситуациях.

На момент написания этой статьи все следующие демонстрации лучше всего просматривать в Chrome или Safari. Firefox планирует поддержка корабля в версии 109.

Случай 1: сетка карт

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

Допустим, вам поручили построить эту сетку карточек с требованием, чтобы каждая карточка сохраняла соотношение сторон 1:1:

Несколько случаев, когда мне помогли бы запросы о размере контейнера

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

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

В моем реальном проекте я остановился на подходе JavaScript, который:

  1. Прослушивание события изменения размера.
  2. Рассчитайте ширину каждой карты.
  3. Добавьте встроенный размер шрифта к каждой карточке в зависимости от ее ширины.
  4. Стилизуйте все внутри, используя em единиц.

Кажется, много работы, верно? Но это стабильное решение для получения необходимого масштабирования на разных размерах экрана в разных контекстах.

Контейнерные запросы были бы намного лучше, потому что они предоставляют нам блоки запроса контейнера, такой как cqw Ед. изм. Вы, наверное, уже поняли, но 1cqw равно 1% ширины контейнера. У нас также есть cqi единица, которая является мерой встроенной ширины контейнера, и cqb для ширины блока контейнера. Итак, если у нас есть контейнер для карт, который 500px широкий, а 50cqw значение вычисляется до 250px.

Если бы я мог использовать контейнерные запросы в своей сетке карточек, я мог бы настроить .card компонент как контейнер:

.card { 
  container: card / size;
}

Тогда я мог бы установить внутреннюю оболочку с padding масштабируется на 10% .cardширина с помощью cqw Блок:

.card__inner { 
  padding: 10cqw; 
} 

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

Еще одна идея? Использовать cqw единиц для размера шрифта внутреннего содержимого, затем примените отступы в em единицы:

.card__inner { 
  font-size: 5cqw; 
  padding: 2em;
} 

5cqw — произвольное значение — именно то, на котором я остановился. Это заполнение по-прежнему равно 10cqw С em единица относится к .card__inner размер шрифта!

Вы уловили это? 2em относительно 5cqw установленный размер шрифта на том же контейнере. Контейнеры работают не так, как мы привыкли, т.к. em единицы относятся к одному и тому же элементу font-size value. Но я быстро заметил, что контейнерные блоки запросов относятся к ближайший родитель, который также является контейнером.

Например, 5cqw не масштабируется на основе .card ширина элемента в этом примере:

.card { 
  container: card / size; 
  container-name: card; 
  font-size: 5cqw; 
}

Скорее, он масштабируется до любого ближайшего родителя, определенного как контейнер. Вот почему я создал .card__inner обертка.

Случай 2: чередование макетов

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

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

Я проделал грязную работу по переводу этого компонента в портретную ориентацию в этих двух конкретных диапазонах области просмотра (привет новый синтаксис диапазона медиа-запросов!), но опять же, проблема в том, что он затем блокируется для заданных для него медиа-запросов, его родителя и всего остального, что может реагировать на ширину области просмотра. Нам нужно что-то, что работает в любых условиях, не беспокоясь о том, где контент сломается!

Запросы контейнеров облегчили бы эту задачу благодаря @container править:

.info-card {
  container-type: inline-size;
  container-name: info-card;
}

@container info-card (max-width: 500px) {
  .info-card__inner {
    flex-direction: column;
  }
}

Один запрос, бесконечная текучесть:

Но держись! Есть кое-что, на что вы, возможно, захотите обратить внимание. В частности, может быть сложно использовать подобный контейнерный запрос в системе дизайна на основе реквизита. Например, это .info-card component может содержать дочерние компоненты, которые полагаются на реквизиты для изменения своего внешнего вида.

Почему это так важно? Книжный макет карты может потребовать альтернативного стиля, но вы не можете изменить реквизиты JavaScript с помощью CSS. Таким образом, вы рискуете дублировать требуемые стили. Я действительно коснулся этого и как это обойти в другой статье. Если вам нужно использовать запросы-контейнеры для значительного количества стилей, вам может понадобиться построить всю систему дизайна вокруг них, а не пытаться впихнуть их в существующую систему дизайна, которая перегружена медиа-запросами.

Случай 3: штрихи SVG

Вот еще один очень распространенный шаблон, который я недавно использовал, когда запросы размера контейнера привели бы к более отточенному продукту. Скажем, у вас есть значок, заблокированный с заголовком:

Heading

Довольно просто масштабировать значок с размером заголовка, даже без медиа-запросов. Проблема, однако, в том, что SVG stroke-width может стать слишком тонким, чтобы быть заметным в меньшем размере, и, возможно, привлечь слишком много внимания сверхтолстым штрихом в большем размере.

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

Блокировка значка шестиугольника и заголовка в трех разных размерах, от большого до маленького.
Несколько случаев, когда мне помогли бы запросы о размере контейнера

Размер шрифта заголовка может быть основан на ширине области просмотра, поэтому значок SVG необходимо настроить соответствующим образом, чтобы его штрих работал при любом размере. Вы можете сделать ширину штриха относительно заголовка font-size установив его в em единицы. Но если у вас есть определенный набор размеров обводки, которого вам нужно придерживаться, то это не сработает, потому что в противном случае масштабирование будет линейным — нет возможности настроить его на конкретный размер. stroke-width значение в определенных точках, не прибегая к медиа-запросам по ширине области просмотра.

Но вот что бы я сделал, если бы в то время у меня была роскошь контейнерных запросов:

.icon {
  container: icon / size; 
  width: 1em; 
  height: 1em; 
}

.icon svg {
  width: 100%; 
  height: 100%; 
  fill: none; 
  stroke: #ccc; 
  stroke-width: 0.8; 
}

@container icon (max-width: 70px) {
  .icon svg {
    stroke-width: 1.5; 
  }
}
@container icon (max-width: 35px) {
  .icon svg {
    stroke-width: 3;
  }
}

Сравните реализации и посмотрите, как версия запроса контейнера привязывает обводку SVG к определенной ширине, которую я хочу, исходя из ширины контейнера.

Бонус: другие типы запросов размера контейнера

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

Большинство примеров, которые я видел, запрашивают width, max-widthи min-width, height, block-sizeи inline-size как я делал на протяжении всей этой статьи.

@container info-card (max-width: 500px) {
  .info-card__inner {
    flex-direction: column;
  }
}

Но MDN описывает еще две вещи мы можем запросить против. Один orientation что имеет смысл, потому что мы постоянно используем его в медиа-запросах. Это ничем не отличается от контейнерных запросов:

@media screen (orientation: landscape) { 
  .info-card__inner {
    /* Style away! */
  }
} 

@container info-card (orientation: landscape) { 
  .info-card__inner {
    /* Style away! */
  }
} 

Другой? Это aspect-ratio, хочешь верь, хочешь нет:

@container info-card (aspect-ratio: 3/2) { 
  .info-card__inner {
    /* Style away! */
  }
} 

Вот редактируемая демонстрация, чтобы поиграть с обоими примерами:

Я еще не нашел хорошего варианта использования ни для одного из них. Если у вас есть какие-либо идеи или вы чувствуете, что это могло бы помочь вам в ваших проектах, дайте мне знать в комментариях!

Отметка времени:

Больше от CSS хитрости