Соотношение сторон (aspect-ratio
) обычно выражается двумя целыми числами с двоеточием: width:height или x:y. Наиболее распространенные соотношения сторон для фотографий – 4:3 и 3:2, а видео, как правило, имеют соотношение сторон 16:9 или 4:3.
С появлением адаптивного дизайна поддержка соотношения сторон стала важной его составляющей: размеры изображений различаются, а размеры элементов меняются в зависимости от доступного пространства. Вот несколько случаев, когда важно поддерживать соотношение сторон:
- iframe, ширина которого 100% от родительской ширины, а высота должна быть пропорциональна ширине.
- подготовка контейнеров для изображений, видео и встраиваемых материалов для предотвращения дёргания и перестройки макета, по мере их загрузки
- единообразное адаптивное пространство для интерактивной визуализации данных (графиков и т.п.) или SVG-анимации
- единообразное адаптивное пространство для многоэлементных компонентов, например – карточки или календарики с датами.
- единообразное адаптивное пространство для нескольких изображений разного размера (можно использовать вместе с
object-fit
)
Встраивание изображений
Определение соотношения сторон помогает устанавливать размеры медиа в адаптивном контексте. Один из инструментов в этом сегменте – css-свойство object-fit
, которое позволяет указывать, как объект (например, изображение) внутри блока должен заполнить этот блок:
Значения initial
и fill
искажают изображение, чтобы заполнить пространство. Это приводит к тому, что изображение может оказаться становится сжатым и размытым. Не идеально.
object-fit: cover
использует размер меньшей из сторон изображения, чтобы заполнить пространство, затем обрезает картинку, чтобы поместить ее в контейнер.
object-fit: contain
гарантирует, что всё изображение всегда будет видимым. Это – противоположность cover
, для вычисления здесь используется большая из сторон, а размеры изображения изменяются так, чтобы сохранить его внутреннее соотношение сторон и вписать его в отведенное пространство.
В случае object-fit: none
изображение обрезается по центру (положение объекта по умолчанию) с естественным размером.
object-fit: cover
часто используется для обеспечения хорошего единообразного интерфейса при работе с изображениями разных размеров, однако при этом может теряться часть информации (изображение обрезается по самым длинным краям).
Если какие-то детали на картинке важны (например, при работе с плоской укладкой косметических товаров), обрезка важного контента может оказаться недопустимой. Таким образом, идеальным вариантом были бы адаптивные изображения разных размеров, которые соответствовали бы пространству пользовательского интерфейса без обрезки.
Старый прием: сохранение соотношения сторон с padding-top
Чтобы сделать их отзывчивыми, можно использовать соотношение сторон. Это позволяет установить определенный размер соотношения и использовать остальную часть носителя на отдельной оси (высоте или ширине).
До настоящего времени широко распространенно кроссбраузерное решение для поддержания соотношения сторон в зависимости от ширины изображения, известное, как «Padding-Top Hack». Для этого решения требуется родительский контейнер и абсолютно спозиционированный дочерний контейнер. Далее требуется рассчитать соотношение сторон в процентах, чтобы установить его как верхнюю часть поля (padding-top
). Например:
- отношение сторон 1:1 = 1 / 1 = 1 =
padding-top: 100%
- отношение сторон 4:3 = 3 / 4 = 0.75 =
padding-top: 75%
- отношение сторон 3:2 = 2 / 3 = 0.66666 =
padding-top: 66.67%
- отношение сторон 16:9 = 9 / 16 = 0.5625 =
padding-top: 56.25%
Теперь, когда разобрались со значениями соотношения сторон, их можно применить родительскому контейнеру. Рассмотрим следующий пример:
<div class="container">
<img class="media" src="..." alt="..." />
</div>
R этому html-коду подойдёт следующий CSS:
.container {
position: relative;
width: 100%;
padding-top: 56.25%; /* отношение 16:9 */
}
.media {
position: absolute;
top: 0;
}
Обеспечение соотношения сторон с помощью aspect-ratio
Вычисление значения padding-top
не очень интуитивно понятно и требует применение позиционирования. С помощью нового css-свойства aspect-ratio
отношение сторон такая же задача решается иначе.
Для html-разметки из примера выше следует заменить padding-top: 56.25%
на aspect-ratio: 16 / 9
, т.е. указать реальное отношение width / height
.
.container {
position: relative;
width: 100%;
padding-top: 56.25%; /* отношение 16:9 */
aspect-ratio: 16 / 9; /* отношение 16:9 */
}
.media {
position: absolute;
top: 0;
}
Использование aspect-ratio
вместо padding-top
намного понятнее и оставляет для свойства padding
его обычное поведение.
Для свойства aspect-ratio
можно установить для соотношения сторон значение auto
, где «замененные элементы с внутренним соотношением сторон используют это соотношение сторон; в противном случае блок не имеет предпочтительного соотношения сторон». Если указать одновременно значения auto
и <ratio>
, то предпочтение будет соотношению сторон, определяемому делением width
на height
, если только это не замещаемый элемент с внутренним соотношением сторон (в этом случае используется его собственное соотношение сторон).
Пример согласованности в сетке (grid)
Этот пример чётко работает с механизмами компоновки, такими как CSS Grid и Flexbox. Рассмотрим список с дочерними элементами, для которых требуется сохранить соотношение сторон 1:1, например сетку логотипов спонсоров:
<ul class="sponsor-grid">
<li class="sponsor">
<img src="..." alt="..." />
</li>
<li class="sponsor">
<img src="..." alt="..." />
</li>
</ul>
.sponsor-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}
.sponsor img {
aspect-ratio: 1 / 1;
width: 100%;
object-fit: contain;
}
Пример предотвращения сдвига макета
Еще одна замечательная особенность css-свойства aspect-ratio
– оно предоставляет возможность реализовать блоки-заглушки (placeholder) для предотвращения сдвига макета (CLS – Cumulative Layout Shift) и предоставления качественных веб-показателей. В первом примере демонстрируется загрузка ресурса из API и получается сдвиг макета, когда загрузка мультимедиа завершится. Проще говоря, текст и блоки страницы скачут и перемещаются, до тех пор, пока все ресурсы загружаются.
Применение css-свойства aspect-ratio
устанавливает контейнеру ожидаемое соотношение сторон и предотвращает сдвиг макета после загрузки мультимедиа:
img {
width: 100%;
aspect-ratio: 8 / 6;
}
Пример использования атрибутов изображения для указания соотношения сторон
Альтернативный способ установить соотношение сторон изображению – использовать его атрибуты. Если заранее известны размеры изображения, можно установить их, c помощью атрибутов width
и height
.
Например, если известно, что размеры изображения составляют 800px на 600px, код разметки для него будет выглядеть так: <img src = "image.jpg" alt = "..." width = "800" height = "600">
. Тогда, если у отправленного изображения будет такое же соотношение сторон, даже не обязательно с точно такими же значениями в пикселях, можно использовать значения атрибутов изображения для установки соотношения в сочетании с css-свойствами width: 100%
и height: auto
, чтобы изображение занимало отведенное пространство. Все вместе это будет выглядеть так:
<img src="image.jpg" alt="..." width="8" height="6">
/* CSS */
img {
width: 100%;
height: auto;
}
В этом случае, эффект будет таким же, как при установке соотношения сторон изображения с помощью CSS aspect-ratio
, и получится избежать кумулятивного сдвига макета.
Завершение
С новым CSS-свойством aspect-ratio
, которое уже работает в нескольких современных браузерах, поддержка правильных соотношений сторон в контейнерах мультимедиа и макета становится проще и понятнее.
New aspect-ratio CSS property supported in Chromium, Safari Technology Preview, and Firefox Nightly.