Декілька запитів розміру контейнера допомогли б мені PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Мені б допомогли декілька запитів про розмір контейнера

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

Але вони, звичайно, зручні! Фактично, я вже стикався з кількома ситуаціями, коли я дійсно хотів дотягнутися до них, але просто не міг подолати вимоги підтримки. Якби я міг ними скористатися, то так би це виглядало в тих ситуаціях.

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

Випадок 1: карткова сітка

Ви мали очікувати цього, чи не так? Це настільки поширена закономірність, що всі ми, здається, колись стикаємося з нею. Але справа в тому, що запити розміру контейнера значно заощадили б для мене час із кращим результатом, якби я міг використовувати їх замість стандартних медіа-запитів.

Припустімо, вам доручили побудувати цю сітку карток із вимогою, щоб кожна картка мала підтримувати співвідношення сторін 1:1:

Мені б допомогли декілька запитів про розмір контейнера

Це складніше, ніж здається! Проблема полягає в тому, що визначення розміру вмісту компонента за шириною вікна перегляду залишає вас на милість того, як компонент реагує на вікно перегляду, а також те, як на нього реагують будь-які інші попередні контейнери. Якщо, наприклад, ви хочете, щоб розмір шрифту заголовка картки зменшувався, коли картка досягає певного вбудованого розміру, немає надійного способу зробити це.

Ви можете встановити розмір шрифту vw одиниць, я припускаю, але компонент все ще прив’язаний до ширини вікна перегляду браузера. І це може спричинити проблеми, коли сітка картки використовується в інших контекстах, які можуть не мати таких самих точок зупину.

У моєму реальному проекті я скористався підходом JavaScript, який:

  1. Слухайте подію зміни розміру.
  2. Обчисліть ширину кожної картки.
  3. Додайте вбудований розмір шрифту до кожної картки залежно від її ширини.
  4. Стилізуйте все всередині за допомогою em одиниць.

Здається, багато роботи, правда? Але це стабільне рішення для отримання необхідного масштабування на різних розмірах екрана в різних контекстах.

Контейнерні запити були б набагато кращими, оскільки вони надають нам контейнерні одиниці запиту, такі як cqw одиниця. Ви, мабуть, уже це зрозуміли, але 1cqw дорівнює 1% ширини контейнера. У нас також є cqi одиниця, яка є мірою внутрішньої ширини контейнера, і cqb для ширини блоку контейнера. Отже, якщо у нас є контейнер для карток 500px широкий, a 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 розмір шрифту!

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

Наприклад, 5cqw не масштабується на основі .card ширина елемента в цьому прикладі:

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

Натомість він масштабується до будь-якого найближчого батьківського елемента, визначеного як контейнер. Ось чому я створив a .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 компонент може містити дочірні компоненти, які залежать від атрибутів для зміни свого зовнішнього вигляду.

Чому це велика справа? Портретний макет картки може вимагати альтернативного стилю, але ви не можете змінити параметри 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-хитрощі