CSS Object-fit та Object-position
object-fit керує тим, як замінювані елементи (<img>, <video>) масштабуються всередині контейнера. object-position задає позицію масштабованого контенту всередині того ж простору.
Теорія
TL;DR
- Уяви фоторамку:
coverобрізає фото, щоб заповнити рамку;containстискає так, щоб все було видно, але з пустим місцем по боках object-fitвідповідає за стратегію масштабування;object-positionза вирівнювання (схожа логіка наbackground-position, але для<img>)- Працює тільки на замінюваних елементах (
<img>,<video>), не на<div> - За замовчуванням стоїть
fill, який розтягує зображення і спотворює пропорції - Правило вибору: для hero-банерів використовуй
cover; для мініатюр -contain
Швидкий приклад
.card-image {
width: 300px;
height: 200px;
object-fit: cover; /* Масштабуємо і обрізаємо зайве */
object-position: center; /* Центр зображення залишається у кадрі */
}Квадратне зображення 400x400, вставлене в блок 300x200, масштабується вгору, рівномірно обрізається зверху і знизу, і залишається відцентрованим. Без спотворень. Це базовий патерн.
Головна різниця
object-fit вибирає стратегію масштабування: розтягнути, вмістити повністю, обрізати до заповнення або залишити оригінальний розмір. object-position потім зсуває результат всередині блоку за координатами 50% 30% або ключовими словами top right. Без явного object-fit браузер використовує fill, який ігнорує пропорції. object-position має ефект тільки після того, як застосовано fit.
Коли що використовувати
- Hero-банер без спотворень:
object-fit: cover; object-position: center - Мініатюри, де видно все зображення:
object-fit: contain; object-position: center - Аватар з обрізанням по обличчю:
object-fit: cover; object-position: 50% 30%(очі ближче до верху) - Відео в letterbox режимі:
object-fit: contain - Логотип в оригінальному розмірі без збільшення:
object-fit: none
Таблиця порівняння
| Значення | Масштабування | Пропорції | Обрізання | Заповнює блок | Коли використовувати |
|---|---|---|---|---|---|
fill | Розтягує до 100% | Спотворює | Ні | Так | Піксель-арт, де спотворення допустиме |
contain | Вміщує повністю | Зберігає | Ні (letterbox) | Ні | Мініатюри, перегляд повного зображення |
cover | Масштабує до заповнення | Зберігає | Так (overflow hidden) | Так | Hero-зображення, картки, аватари |
none | Без масштабування | Зберігає | Можливо | Ні | Логотипи, важливий оригінальний розмір |
scale-down | Обмежує до оригінального розміру | Зберігає | Ні | Ні | Великі зображення, які не потрібно збільшувати |
Типові помилки
1. Застосування object-fit до <div>
/* Неправильно: object-fit ігнорується на не-замінюваних елементах */
.box {
object-fit: cover;
background: url(img.jpg); /* Не має жодного ефекту */
}
/* Правильно: для div використовуй background-size */
.box {
background: url(img.jpg) center / cover no-repeat;
}2. Відсутність width і height на зображенні
/* Неправильно: без розмірів object-fit не знає з чим працювати */
.container { height: 200px; }
img { object-fit: cover; }
/* Правильно */
img {
width: 100%;
height: 100%;
object-fit: cover;
}Зображенню потрібні явні розміри. Без них воно відображається у своїх природних розмірах і object-fit нічого не робить видимого. Це найпоширеніший баг з цим пропсом.
3. Портретне зображення в горизонтальному блоці з cover - несподіване обрізання
cover обрізає той вимір, що виходить за межі блоку. Висока вертикальна фотографія в широкому горизонтальному блоці втратить боки. Рішення: object-position: center top, щоб голова залишилась у кадрі.
Де зустрічається в реальному коді
- Next.js
<Image>зfilllayout використовуєobject-fit: coverвсередині для адаптивного кадрування - TailwindCSS має класи
object-cover,object-contain,object-center, які використовуються в сотнях тисяч проєктів - Video.js використовує
object-fit: containдля адаптивних відеовставок - Для декоративних фонів на div використовуй
background-size: cover.object-*призначений для семантичних зображень з атрибутомalt
Можливі питання на співбесіді
Q: Яке значення object-fit стоїть за замовчуванням?
A: fill. Воно розтягує зображення точно під width і height, спотворюючи пропорції.
Q: Чим відрізняється object-position: bottom від object-position: 50% 100%?
A: Нічим. Ключові слова CSS відображаються у відсотки: top = 50% 0%, bottom = 50% 100%, center = 50% 50%.
Q: Чи працює object-fit на <canvas> або <svg>?
A: На <svg>, вставленому як замінюваний елемент через <img src="icon.svg">, так. <canvas> потребує ручного масштабування в JavaScript.
Q: Що відбувається, коли браузер ще не знає розміри зображення, наприклад при lazy load?
A: Браузер використовує розмір за замовчуванням 300x150 пікселів. object-fit обчислюється на цій основі, а потім перераховується після завантаження. Без aspect-ratio на контейнері отримуєш зміщення layout. Рішення: поєднуй object-fit з aspect-ratio на обгортці.
Приклади
Hero-банер з cover
.hero {
width: 100%;
height: 500px;
overflow: hidden;
}
.hero img {
width: 100%;
height: 100%;
object-fit: cover; /* Заповнення без спотворення */
object-position: center; /* Центруємо точку обрізання */
}Зображення заповнює всю ширину на будь-якому viewport. Які б не були оригінальні розміри, браузер масштабує і обрізає автоматично. Це патерн за кожним повноширинним банером.
Аватар користувача з фокусом на обличчі
.avatar {
width: 80px;
height: 80px;
border-radius: 50%;
overflow: hidden;
}
.avatar img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 30%; /* Точка обрізання у верхній третині - очі залишаються у колі */
}Значення 30% від верху зсуває кадрування вгору. Обличчя залишається у центрі кола замість чола або підборіддя.
Галерея із зафіксованими пропорціями
.gallery-item {
width: 100%;
aspect-ratio: 16 / 9; /* Форма блоку не залежить від розмірів зображення */
overflow: hidden;
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
transition: transform 0.3s;
}
.gallery-item:hover img {
transform: scale(1.05);
}Поєднання aspect-ratio з object-fit: cover прибирає потребу у фіксованих значеннях height. Блок зберігає форму 16:9; зображення заповнює його на будь-якому viewport.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.