Как использовать object-fit и background-size в CSS

 alexei 06/11/2021 - 09:01
Как использовать object-fit и background-size в CSS

Мы не всегда можем предоставить для HTML элемента изображение нужного размера. Если же мы используем контейнер с шириной и высотой, которые не пропорциональны соотношению сторон изображения, то изображение будет либо сжато, либо растянуто. Это выглядит нехорошо, однако решить эту проблему можно либо применив свойство object-fit к элементу img, либо с помощью свойства background-size.

Для начала давайте определимся с проблемой. Посмотрите на следующий рисунок:

Нормальное и сжатое изображение
Нормальное изображение, которое сжимается при использовании в HTML компоненте.

Почему это происходит?

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

Мы видим это на следующем рисунке:

Нормальное и растянутое изображение
Соотношение сторон изображения отличается от размеров содержащего ее элемента, и изображение выводится растянутым.

Решение проблемы

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

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

Теперь, когда мы понимаем, как это работает, давайте разберемся, как это работает в браузере.

CSS свойство object-fit

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

Давайте рассмотрим возможные значения.

object-fit: contain

В этом случае размер изображения будет изменен в соответствии с соотношением сторон контейнера. Если соотношение сторон изображения не совпадает с соотношением сторон контейнера, то оно будет дополнено черными каше.

object-fit: contain
При использовании object-fit: contain изображение будет либо подогнано под размеры контейнера, либо дополнено черными полосами (каше).

object-fit: cover

В этом случае размер изображения также будет изменен в соответствии с соотношением сторон контейнера, и если соотношение сторон изображения не соответствует размеру контейнера, оно будет обрезано по размеру.

object-fit: cover
При использовании object-fit: cover изображение будет либо подогнано под размеры контейнера, либо обрезано.

object-fit: fill

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

object-fit: fill
При использовании object-fit: fill изображение будет либо подогнано под размеры контейнера, либо сжато/растянуто.

object-fit: none

В этом случае размер изображения вообще не будет изменен, ни растянут, ни сжат. Это значение работает так же, как значение cover, но при этом не учитывается соотношение сторон контейнера.

object-fit: none
При использовании object-fit: none размер изображения не будет изменен, если он не соответствует размеру контейнера.

Кроме свойства object-fit, еще есть свойство object-position, которое отвечает за положение изображения внутри контейнера.

Возможные значения свойства object-position

Свойство object-position работает аналогично свойству CSS background-position:

object-position: center, left, right
В большинстве случаев используется значение по умолчанию (т. е. "center" или "50% 50%").

Ключевые слова top и bottom также работают, когда соотношение сторон контейнера по вертикали больше:

object-position: top и bottom
Сравнение object-position: top (слева) и object-position: bottom (справа).

Свойство background-size

Основное отличие свойства background-size заключается в том, что мы имеем дело с фоном, а не с HTML элементом (img).

Возможные значения background-size

Свойство background-size может принимать значения auto, contain и cover.

background-size: auto

При значении auto изображение сохраняет свой оригинальный размер:

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

background-size: cover

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

background-size: cover
При использовании background-size: cover обязательно учитывайте соотношение сторон изображения.

background-size: contain

В этом случае размер изображения будет изменен таким образом, чтобы оно помещалось в контейнер. Если соотношение сторон не совпадает, то изображение будет дополнено черными полосами (каше), как показано в следующем примере:

background-size: contain
background-size: contain изменяет размер изображение, чтобы оно поместилось в контейнер.

Что касается background-position, то оно работает также, как object-position. Единственное отличие состоит в том, что позиция по умолчанию object-position отличается от позиции по умолчанию background-position.

Когда не следует использовать object-fit или background-size

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

Рассмотрим следующий пример, в котором изображению задана фиксированная высота:


.card__thumb {
    height: 220px;
}

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

Если контейнер слишком широк, это приведет к результату, который мы видим на рисунке справа (изображение слишком широкое). Это происходит потому, что мы не задаем соотношение сторон.

Решить эту проблему можно только двумя способами. Первый - это использовать трюк под названием "padding hack", чтобы создать внутреннее соотношение сторон.


.card__thumb {
    position: relative;
    padding-bottom: 75%;
    height: 0;
}

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

Второй способ это использовать новое CSS свойство aspect-ratio:


.card__thumb img {
    aspect-ratio: 4 / 3;
}

Случаи использования и примеры

Аватары пользователей

Идеальный вариант использования object-fit: cover - это аватары пользователей. Обычно соотношение сторон, допустимое для аватара, квадратное. Размещение изображения в квадратном контейнере может исказить изображение.

Аватар пользователя без object-fit и с object-fit: cover
Аватар пользователя без object-fit и с object-fit: cover

.c-avatar {
    object-fit: cover;
}

Список логотипов

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

К счастью, для этого отлично подходит object-fit: contain.


.logo__img {
    width: 150px;
    height: 80px;
    object-fit: contain;
}

Список логотипов: Airbnb, Domino’s Pizza, Apple Pay, Amazon
Использование object-fit: contain поможет подогнать под один размер логотипы клиентов не искажая их.

Миниатюра для статьи

Это очень распространенный вариант использования. Контейнер для миниатюры статьи может не всегда содержать изображение с одинаковым соотношением сторон. Эта проблема в первую очередь должна устраняться системой управления контентом (CMS), но это происходит не всегда.


.article__thumb {
    object-fit: cover;
}

Миниатюра статьи
Настройка миниатюры статьи при помощи object-fit: cover.

Задний фон заголовка статьи

В этом случае решение о том, использовать элемент img или фон CSS будет зависеть от следующего:

  • Имеет ли изображение важное значение? Если CSS по какой-то причине будет отключен, хотим ли мы, чтобы пользователь видел изображение?
  • Или же у изображения просто декоративное назначение?

Основываясь на ответе на эти вопросы, мы можем решить, какой способ использовать. Если изображение важно:

Задний план для заголовка статьи
Давайте предположим, что изображение важно, потому что это веб-сайт, связанный с едой.

<section class="hero">
    <img class="hero__thumb" src="//msiter.ru/thumb.jpg" alt="" />
</section>


.hero {
    position: relative;
}

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

Если изображение имеет чисто декоративную функцию, то мы можем использовать свойство background-image:


.hero {
    position: relative;
    background-image: linear-gradient(to top, #a34242, rgba(0,0,0,0), url("thumb.jpg");
    background-repeat: no-repeat;
    background-size: cover;
}

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

Добавление фона к изображению при помощи object-fit: contain

А вы знаете, что вы можете добавить цвет фона для img? Это еще один плюс при использовании object-fit: contain.

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


img {
    object-fit: contain;
    background-color: #def4fd;
}

Добавления фонового цвета изображения при помощи object-fit: contain
Можно использовать object-fit: contain, чтобы добавить фоновый цвет изображению.

Видеоэлемент

Требовалось ли вам когда-нибудь установить видео в качестве фона? Если да, то вы, вероятно, хотели бы, чтобы оно занимало бы всю ширину и высоту родительского элемента.


.hero {
    position: relative;
    background-color: #def4fd;
}

.hero__video {
    position: aboslute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
}

Рисунок, где видео не заполняет полностью фон заголовка
У элемента video по умолчанию стоит значение object-fit: contain. Как видно на рисунке, в этом случае видео не заполняет полностью фон, даже если у него заданы свойства position: absolute, width: 100% и height: 100%.

Чтобы видео полностью заполнило родительский элемент, нам нужно переопределить значение по умолчанию у object-fit:


.hero__video {
    /* другие стили */
    object-fit: cover;
}

Заключение

Как вы, наверное, убедились, свойства object-fit и background-size очень полезны для обработки изображений с различными соотношениями сторон. Мы не всегда можем контролировать настройку идеальных размеров для каждого изображения, и именно здесь эти два CSS свойства незаменимы.

И еще стоит дружески напомнить о выборе между элементом img и фоном CSS: Если изображение является чисто декоративным, выбирайте фон CSS. В противном случае более подходит элемент img.

Надеемся, что данная статья была вам полезна. Спасибо, что дочитали ее до конца.