Мы не всегда можем предоставить для HTML элемента изображение нужного размера. Если же мы используем контейнер с шириной и высотой, которые не пропорциональны соотношению сторон изображения, то изображение будет либо сжато, либо растянуто. Это выглядит нехорошо, однако решить эту проблему можно либо применив свойство object-fit
к элементу img
, либо с помощью свойства background-size
.
Для начала давайте определимся с проблемой. Посмотрите на следующий рисунок:
Почему это происходит?
Браузер заполняет содержащий изображение элемент заданным изображением. При этом у любого изображения есть свое соотношение сторон. И если соотношение сторон изображения отличается от указанных для него ширины и высоты, то результатом будет либо сжатое, либо растянутое изображение.
Мы видим это на следующем рисунке:
Решение проблемы
Нам не всегда нужно добавлять изображение другого размера, если соотношение сторон изображения не совпадает с шириной и высотой контейнера. Прежде чем погрузиться в CSS-решения, мы хотим показать вам, как мы делали это в приложениях для редактирования изображений:
Теперь, когда мы понимаем, как это работает, давайте разберемся, как это работает в браузере.
CSS свойство object-fit
Свойство object-fit
определяет, как должен измениться размер содержимого заменяемого элемента, например, img
или video
, чтобы подстроиться под контейнер. По умолчанию object-fit
имеет значение fill
, что может привести к сжиманию или растягиванию изображения.
Давайте рассмотрим возможные значения.
object-fit: contain
В этом случае размер изображения будет изменен в соответствии с соотношением сторон контейнера. Если соотношение сторон изображения не совпадает с соотношением сторон контейнера, то оно будет дополнено черными каше.
object-fit: cover
В этом случае размер изображения также будет изменен в соответствии с соотношением сторон контейнера, и если соотношение сторон изображения не соответствует размеру контейнера, оно будет обрезано по размеру.
object-fit: fill
При этом значении размер изображения будет изменен в соответствии с соотношением сторон контейнера, и если соотношение сторон изображения не соответствует размеру контейнера, оно будет либо сжато, либо растянуто. Но мы этого не хотим.
object-fit: none
В этом случае размер изображения вообще не будет изменен, ни растянут, ни сжат. Это значение работает так же, как значение cover
, но при этом не учитывается соотношение сторон контейнера.
Кроме свойства object-fit
, еще есть свойство object-position
, которое отвечает за положение изображения внутри контейнера.
Возможные значения свойства object-position
Свойство object-position
работает аналогично свойству CSS background-position
:
Ключевые слова top
и bottom
также работают, когда соотношение сторон контейнера по вертикали больше:
Свойство background-size
Основное отличие свойства background-size
заключается в том, что мы имеем дело с фоном, а не с HTML элементом (img
).
Возможные значения background-size
Свойство background-size
может принимать значения auto
, contain
и cover
.
background-size: auto
При значении auto
изображение сохраняет свой оригинальный размер:
background-size: cover
В этом случае размер изображения будет изменен таким образом, чтобы оно помещалось в контейнер. Если пропорции не совпадают, то изображение будет обработано таким образом, чтобы оно подошло под размеры контейнера.
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
- это аватары пользователей. Обычно соотношение сторон, допустимое для аватара, квадратное. Размещение изображения в квадратном контейнере может исказить изображение.
.c-avatar {
object-fit: cover;
}
Список логотипов
Список клиентов бизнеса имеет важное значение. Обычно для этого используют их логотипы. Поскольку логотипы часто бывают разных размеров, нам нужен способ изменить их размер без искажения.
К счастью, для этого отлично подходит object-fit: contain
.
.logo__img {
width: 150px;
height: 80px;
object-fit: contain;
}
Миниатюра для статьи
Это очень распространенный вариант использования. Контейнер для миниатюры статьи может не всегда содержать изображение с одинаковым соотношением сторон. Эта проблема в первую очередь должна устраняться системой управления контентом (CMS), но это происходит не всегда.
.article__thumb {
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;
}
Видеоэлемент
Требовалось ли вам когда-нибудь установить видео в качестве фона? Если да, то вы, вероятно, хотели бы, чтобы оно занимало бы всю ширину и высоту родительского элемента.
.hero {
position: relative;
background-color: #def4fd;
}
.hero__video {
position: aboslute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
Чтобы видео полностью заполнило родительский элемент, нам нужно переопределить значение по умолчанию у object-fit
:
.hero__video {
/* другие стили */
object-fit: cover;
}
Заключение
Как вы, наверное, убедились, свойства object-fit
и background-size
очень полезны для обработки изображений с различными соотношениями сторон. Мы не всегда можем контролировать настройку идеальных размеров для каждого изображения, и именно здесь эти два CSS свойства незаменимы.
И еще стоит дружески напомнить о выборе между элементом img
и фоном CSS: Если изображение является чисто декоративным, выбирайте фон CSS. В противном случае более подходит элемент img
.
Надеемся, что данная статья была вам полезна. Спасибо, что дочитали ее до конца.