Три способа размещения изображения в адаптивном контейнере с заданными пропорциями
Задача
Сверстать адаптивный контейнер для изображения, который станет частью компонента: карточки-превью (товара, записи блога, статьи).
Условия
- Контейнер имеет заданные пропорции.
- Контейнер адаптивен, то есть при уменьшении ширины пропорции сохраняются.
- В контейнере можно размещать изображения с любым соотношением сторон, они вписываются в блок без искажения пропорций.
Предлагаемые способы
- Флекс-контейнер.
- Использование css-свойства object-fit.
- Фоновое изображение.
Реализация. HTML
Для всех способов мы используем одинаковую структуру, с той разницей, что в случае использования фонового изображения не требуется элемент <img>.
<div class="adaptive-container">
<div class="object-wrap">
<div class="object-wrap__mid">
<figure class="object-wrap__inner object-box object-box_object-fit">
<img src="cat-v.jpg" class="image" alt="">
</figure>
</div>
</div>
</div>
.adaptive-container — родительский компонент с вариативной шириной. Какой-нибудь .product-card для превью товара, например.
.object-wrap — внешняя обёртка со стопроцентной шириной, относительно родительского контейнера.
.object-wrap__mid — промежуточная обёртка, отвечающая за адаптивную высоту, которая достигается нулевой высотой и относительным нижним полем.
.object-wrap__inner, он же .object-box — основной ящик для картинки. Абсолютно спозиционирован, имеет стопроцентную высоту и ширину. В зависимости от способа размещения иллюстрации, имеет или фоновое изображение или вложенный <img>.
Реализация. CSS
.adaptive-container {
width: 320px;
}
.object-wrap {
width: 100%;
}
.object-wrap__mid {
width: 100%;
height: 0;
padding-bottom: 75%;
position: relative;
background:lightblue;
}
.object-wrap__inner {
width: 100%;
height: 100%;
position: absolute;
}
/* 1. Флекс-контейнер */
.object-box_flexbox {
display: flex;
justify-content: center;
align-items: center;
}
.object-box_flexbox .image {
max-width: 100%;
max-height: 100%;
}
/* 2. object-fit */
.object-box_object-fit .image {
width: 100%;
height: 100%;
object-fit: contain;
background:lightblue;
}
/* 3. фоновое изображение */
.object-box_background {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
Важно помнить что свойства object-fit и object-position применяются к объекту и не работают если у последнего не заданы ширина и высота.
Поддержка браузерами
flexbox— 99,5%object-fitиobject-position— 97,8%background-sizeиbackground-position— 96,2%
Выводы
Технически все предложенные способы имеют достаточную для широкого применения браузерную поддержку.
Однако, при выборе способа вставки картинки стоит помнить, что для поисковых роботов, скринридеров и т. п. фоновое изображение — это оформление, а <img> — контент. Поэтому если вы не можете дать чёткий ответ на вопрос зачем вы вставляете фотографию фоном, не делайте так, используйте <img>.
Сравнивая два способа вставки <img>, я бы остановился на модели, использующей object-fit. Этот вариант надёжней флекс-контейнера, который при изменении собственных пропорций может искажать вложенное изображение со стопроцентной максимальной шириной и высотой (в песочнице этот баг получается воспроизвести).
Также object-fit позволяет полностью заполнять контейнер изображением, аналогично бэкграунду.
Песочница