Печатает... Список заметок

Три способа размещения изображения в адаптивном контейнере с заданными пропорциями

Задача

Сверстать адаптивный контейнер для изображения, который станет частью компонента: карточки-превью (товара, записи блога, статьи).

Условия

  1. Контейнер имеет заданные пропорции.
  2. Контейнер адаптивен, то есть при уменьшении ширины пропорции сохраняются.
  3. В контейнере можно размещать изображения с любым соотношением сторон, они вписываются в блок без искажения пропорций.

Предлагаемые способы

  1. Флекс-контейнер.
  2. Использование css-свойства object-fit.
  3. Фоновое изображение.

Реализация. 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 применяются к объекту и не работают если у последнего не заданы ширина и высота.

Поддержка браузерами

  1. flexbox — 99,5%
  2. object-fit и object-position — 97,8%
  3. background-size и background-position — 96,2%

Выводы

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

Однако, при выборе способа вставки картинки стоит помнить, что для поисковых роботов, скринридеров и т. п. фоновое изображение — это оформление, а <img> — контент. Поэтому если вы не можете дать чёткий ответ на вопрос зачем вы вставляете фотографию фоном, не делайте так, используйте <img>.

Сравнивая два способа вставки <img>, я бы остановился на модели, использующей object-fit. Этот вариант надёжней флекс-контейнера, который при изменении собственных пропорций может искажать вложенное изображение со стопроцентной максимальной шириной и высотой (в песочнице этот баг получается воспроизвести).

Также object-fit позволяет полностью заполнять контейнер изображением, аналогично бэкграунду.

Песочница

Формат изображения:
Формат контейнера:
Вывод:
Дополнительные параметры
justify-content:
align-items: