CSS: Соотношение сторон или aspect-ratio

Источник: «Let's Learn About Aspect Ratio In CSS»
Важно иметь постоянное соотношение ширины и высоты изображений и других отзывчивых элементов. Мы много лет использовали в CSS хак с отступами, но сейчас у нас есть встроенная поддержка соотношения сторон в CSS. В этой статье я расскажу, что такое соотношение сторон, как мы его использовали и как это делать по-новому. Конечно, будут варианты использования с подходящими запасными вариантами.

Введение: Что такое соотношение сторон?

Из Wikipedia

Соотношение в математике (отношение, пропорция) — это взаимосвязь между двумя однородными числовыми величинами. Обычно выражается как a к b или a:b. Иногда представляется арифметически как результат (не обязательно целочисленный) деления двух числовых значений, непосредственно отображающий, сколько раз первое число содержит второе.

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

Рассмотрим рисунок.

Рисунок

У нас соотношение 4:3. Мы можем увидеть это по соотношению яблок к винограду — оно равно четыре к трём.

Другими словами, самый маленький прямоугольник, который мы можем создать для соотношения сторон 4:3, это прямоугольник 4 * 3 пикселя. Когда высота этого блока изменяется пропорционально его ширине, у нас будет блок соответствующим ему соотношению сторон.

Рассмотрим следующий рисунок.

Неизменное соотношение сторон при изменении размера

Размер поля изменяется пропорционально, и соотношение между его шириной и высотой остаётся неизменным. А теперь представим, что прямоугольник содержит важное изображение, и мы заботимся обо всех его деталях.

Масштабирование важного изображения

Обратите внимание, что детали размера сохраняются независимо от размера. Имея постоянное соотношение сторон, мы можем получить следующие преимущества:

Измерение соотношения сторон

Чтобы измерить соотношение сторон, нам нужно разделить ширину на высоту, как показано на следующем рисунке.

Измерение соотношения сторон

Соотношение ширины и высоты: 1,33. Значит это соотношение следует соблюдать. Учтите следующее:

Соотношение сторон

Обратите внимание на изображение справа, отношение ширины к высоте равно 1.02, что не соответствует исходному соотношению сторон (1.33 или 4:3).

Вы можете подумать, как привести его к 4:3? Ну, это называется Ближайшим Нормальным Соотношением Сторон, и есть инструменты, которые могут помочь нам в его поиске. При работе над дизайном пользовательского интерфейса настоятельно рекомендуется знать точное соотношение сторон изображений, которые вы будете использовать. Калькулятор может в этом помочь.

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

Реализация aspect-ratio в CSS

Мы привыкли реализовывать соотношение сторон, через внутренние отступы в CSS. Хорошая новость в том, что недавно мы получили встроенную поддержку соотношения сторон aspect-ratio — во всех браузерах. Прежде чем прейти к новому способу, я немного расскажу про старый добрый способ решения проблемы с помощью padding.

Соотношение сторон

Когда заголовок имеет padding: 50%, значение вычисляется на основе ширины его родительского элемента. Поскольку ширина родительского элемента составляет 200px, padding-top станет равен 100px.

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

Учтите, что ширина изображения составляет 260px, высота — 195px.

Проценты внутреннего отступа = высота / ширина

Результат 195/260 — 0.75 (или 75%).

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

Сетка из карточек

По какой-то причине автор контента загрузил изображение, размер которого не соответствует другим. Обратите, как высота средней карточки не равна высоте других.

Вы могли бы подумать, что мы можем добавить фиксированную высоту и object-fit: cover Проблема решена, правда? Это не так просто. Это решение будет плохо смотреться при разных размерах экрана.

Сетка из карточек

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

Нам нужен постоянный размер миниатюр вне зависимости от размера экрана. Для этого нужно реализовать соотношение сторон, используя процентное заполнение padding.

<article class="card">
<div class="card__thumb">
<img src="thumb.jpg" alt="" />
</div>
<div class="card__content">
<h3>Muffins Recipe</h3>
<p>Servings: 3</p>
</div>
</article>
.card__thumb {
position: relative;
padding-top: 75%;
}

.card__thumb img {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
object-fit: cover;
}

С учётом вышеизложенного мы определили, что высота обёртки миниатюры карточки (.card__thumb) зависит от её ширины. Кроме того, изображение абсолютно позиционировано и имеет полную высоту и ширину своего родителя, с object-fit: cover для случаев с загрузкой изображения другого размера. Теперь размер карточки может меняться без изменения соотношения сторон.

Представляем CSS свойство aspect-ratio

Ранее в этом году CSS свойство aspect-ratio было поддержано в Chrome, Safari TP и Firefox Nightly. Недавно оно получило поддержку в официальной версии Safari 15.

Сейчас aspect-ratio поддерживается всеми современными браузерами, кроме Internet Explorer.

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

Если мы вернёмся к предыдущему примеру, то мы можем переписать его так:

/* Текущий способ */
.card__thumb {
position: relative;
padding-top: 75%;
}

/* С поддержкой aspect-ratio */
.card__thumb {
position: relative;
aspect-ratio: 4/3;
}

Посмотрите на интерактивном примере, как процентное соотношение меняется.

See the Pen

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

Прогрессивное улучшение

Сегодня мы можем использовать CSS свойство aspect-ratio используя CSS запрос @support и CSS переменные. Я узнал об этом из замечательной статьиПитера-Поля Коха (Peter-Paul Koch)

.card {
--aspect-ratio: 16/9;
padding-top: calc((1 / (var(--aspect-ratio))) * 100%);
}

@supports (aspect-ratio: 1) {
.card {
aspect-ratio: var(--aspect-ratio);
padding-top: initial;
}
}

Варианты использования

Наиболее распространённый вариант использования aspect-ratio — карточки с изображениями. Поскольку я уже рассказал об этом, то не буду вдаваться в подробности.

Изображения логотипов

В прошлом году я опубликовал статью о том, как правильно выровнять логотипы разного размера с помощью CSS свойства object-fit и позиционирования. Теперь с CSS свойством aspect-ratio это стало ещё проще.

Давайте посмотрим на эти логотипы.

Логотипы

Вы заметили, что у них одинаковый размер и они выровнены? Давайте заглянем в код:

<li class="brands__item">
<a href="#">
<img src="assets/batch-2/aanaab.png" alt="" />
</a>
</li>
.brands__item a {
padding: 1rem;
}

.brands__item img {
width: 130px;
object-fit: contain;
aspect-ratio: 2/1;
}

Я добавил базовую ширину 130px что бы получить минимальный размер, а aspect-ratio позаботится о высоте.

Внутренние отступы логотипов

Синяя область — это размер изображения, и важно использовать object-fit, что бы избежать искажения изображения.

Отзывчивые круги

Да! Вам когда-нибудь нужно было создать округлый элемент, который должен быть отзывчивым? CSS свойство aspect-ratio идеально подходит для этого.

Круглые элементы
.person {
width: 180px;
aspect-ratio: 1;
}

Если оба значения для которых высчитывается соотношение сторон равны, мы можем записать aspect-ratio: 1, вместо aspect-ratio: 1/1. Если вы используете CSS Grid или CSS Flexbox, ширина будет не обязательной, и её можно добавить в качестве минимального значения.

Внешние ссылки

Это вариант использования с которым я недавно столкнулся в клиентском проекте. У меня есть компонент с внешними ссылками. Сначала я сделал их с внутренним отступом, который нужно изменять на мобильном устройстве.

Компонент с внешними ссылками

С aspect-ratio мы можем заставить его реагировать на ширину родительского элемента без необходимости настраивания внутреннего отступа на мобильных устройствах (т.е. уменьшать его)

Дополнительные материалы

Предыдущая Статья

CSS: Пропорциона­ль­ное масштабиро­ва­ние с css-переменными

Следующая Статья

Symfony: Обновление основной версии (c 5.4.0 до 6.0.0)