CSS: Соотношение сторон или aspect-ratio
Введение: Что такое соотношение сторон?
Из 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;
}
Посмотрите на интерактивном примере, как процентное соотношение меняется.
Итак, давайте рассмотрим некоторые варианты использования, в которых поддержка браузерами соотношения сторон может быть полезно, и как использовать его в прогрессивно улучшенном подходе.
Прогрессивное улучшение
Сегодня мы можем использовать 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
мы можем заставить его реагировать на ширину родительского элемента без необходимости настраивания внутреннего отступа на мобильных устройствах (т.е. уменьшать его)