CSS співвідношення сторін
aspect-ratio, це CSS властивість, що автоматично обчислює висоту елемента з його ширини (або навпаки) за фіксованим співвідношенням.
Теорія
TL;DR
- Як рамка для фото, що підлаштовує висоту під будь-яку ширину без спотворень. Ти задаєш пропорцію, браузер рахує.
- До 2021 року: трюк з
padding-bottom: 56.25%на div-обгортці. Тепер одна властивість замінює все це. - Задай один розмір (ширину або висоту) плюс
aspect-ratio, браузер обчислить інший. - Пропускай, якщо обидва розміри вже задані явно.
Швидкий приклад
.video {
width: 100%;
max-width: 800px;
aspect-ratio: 16 / 9;
background: #000;
}
/* При ширині 800px висота 450px. При 400px висота 225px. */Одна властивість. Без JavaScript. Без padding-хаків. Контейнер залишається 16:9 при будь-якому розмірі вікна.
Чому це замінило padding-хак
До Chrome 88 (січень 2021) відсоткова height не мала точки відліку, якщо батьківський елемент не мав явної висоти. Тому розробники застосовували padding-bottom: 56.25% на обгортці, бо відсоткові відступи завжди рахуються від ширини. div з height: 0; padding-bottom: 56.25% давав блок 16:9, а реальний контент розміщувався всередині через position: absolute.
Працювало. Але це був хак. Зайва розмітка, неочевидний CSS, плутанина для всіх, хто читав код пізніше. На практиці я досі зустрічаю цей патерн у проєктах, що стартували до 2021 року, часто просто скопійований без усвідомлення, що існує нативне рішення.
aspect-ratio вирішує це напряму. Браузер рахує висота = ширина * (ratio-height / ratio-width) під час layout-проходу, після того як ширина вже відома. Без обгорток. Без padding-трюків.
Коли використовувати
- Адаптивні відео-контейнери:
width: 100%+aspect-ratio: 16 / 9 - Мініатюри в галереях, що масштабуються з шириною колонки Grid
- Картки товарів, де зображення має зберігати форму при зміні розміру
- Placeholder-блоки до завантаження зображень
Пропускай, якщо width і height задані явно. Тоді властивість ігнорується. Також не потрібна, якщо Flexbox або Grid вже контролює потрібну форму.
Як браузер це обчислює
Браузери (Blink, WebKit, Gecko) обробляють aspect-ratio під час layout-проходу, після визначення ширини. Для блокового елемента з width: 100% ширина відома першою, тому висота обчислюється з пропорції. У вертикальному flex-контейнері з обмеженою висотою логіка зворотна. Якщо задані обидва розміри явно, пропорція ігнорується повністю.
Важливий edge case: min-height і max-height можуть перебити обчислений через ratio розмір. Якщо обчислена висота менша за min-height, браузер бере min-height, і aspect-ratio фактично перестає діяти.
Типові помилки
Задавати height разом з aspect-ratio у Flexbox:
/* Неправильно - height перебиває ratio */
.flex-item {
flex: 1;
aspect-ratio: 16 / 9;
height: 100%;
}
/* Правильно - прибери height, нехай ratio встановить його */
.flex-item {
flex: 1;
aspect-ratio: 16 / 9;
}Думати, що aspect-ratio: auto зберігає власні пропорції зображення на всіх елементах:
Для replaced elements (img, video) auto дійсно бере власну пропорцію з файлу. Але для звичайних div — це 1:1. Для зображень простіший шлях: width: 100%; height: auto;.
Застосовувати до комірок таблиці:
Table layout ігнорує aspect-ratio. Алгоритм таблиці перебиває його. Обгорни контент комірки у div і застосовуй ratio там.
Батьківський елемент схлопується до нуля у float-контексті:
Якщо батько не має точки відліку для висоти, ratio не може спрацювати. Використовуй Flexbox або Grid як контейнер, або задай батьку явну висоту.
Де зустрічається
- Tailwind CSS: утиліта
aspect-[16/9]з v3+ - Bootstrap 5.3+: клас
.ratioвикористовуєaspect-ratioз@supportsfallback для старих браузерів - Next.js / Vercel templates: контейнери для відео і hero-зображень
- Бібліотека react-player: обгортає iframe з
aspectRatioв inline-стилях замість старого padding-підходу - Legacy-підтримка:
@supports not (aspect-ratio: 1) { padding-bottom: 56.25%; }для Safari до версії 15
Питання на співбесіді
Q: Що буде, якщо задати і width, і height разом з aspect-ratio?
A: Пропорція ігнорується. Явні розміри завжди мають пріоритет. aspect-ratio обчислює лише той розмір, якого не вистачає.
Q: Як працює aspect-ratio: auto на зображеннях?
A: Для replaced elements (img, video) auto бере власну пропорцію з файлу. Для звичайних елементів за замовчуванням 1:1. Для зображень зазвичай простіше width: 100%; height: auto;.
Q: Як підтримувати браузери до Chrome 88?
A: Використовуй @supports not (aspect-ratio: 1) і додай padding-bottom як fallback. Окремий поліфіл не потрібен, достатньо прогресивного покращення.
Q: Чому в CSS Grid aspect-ratio іноді ігнорується на елементах сітки?
A: Grid спочатку обчислює розміри треків. Якщо рядок має явну висоту або grid розтягує елементи, ця висота перебиває пропорцію. Рішення: align-items: start на контейнері, або перенеси ratio на внутрішній div всередині елемента сітки.
Q: Чи можна використовувати CSS-змінні з aspect-ratio?
A: Так. aspect-ratio: var(--ratio) працює. Оголоси --ratio: 16 / 9 у :root і використовуй у кількох компонентах.
Приклади
Адаптивне відео
Класичний випадок. iframe залишається 16:9 при будь-якій ширині екрана, без padding-хаку і без JavaScript.
<div class="video-wrapper">
<iframe
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
style="width: 100%; height: 100%; border: none;"
allowfullscreen>
</iframe>
</div>.video-wrapper {
width: 100%;
max-width: 800px;
aspect-ratio: 16 / 9;
margin: 0 auto;
overflow: hidden;
/* Без position: absolute. Без padding-bottom. Просто працює. */
}При ширині 800px висота буде 450px. При 400px висота буде 225px. iframe заповнює обгортку, бо його ширина і висота дорівнюють 100% від батька, а висота батька задається через ratio.
Сітка товарів з однаковими мініатюрами
Інтернет-магазини потребують квадратних мініатюр незалежно від розмірів оригінального зображення. aspect-ratio фіксує форму, object-fit обробляє кадрування.
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
.product-image {
width: 100%;
aspect-ratio: 1 / 1; /* завжди квадрат */
overflow: hidden;
background: #f5f5f5;
border-radius: 4px;
}
.product-image img {
width: 100%;
height: 100%;
object-fit: cover; /* кадрування, не розтягування */
}object-fit: cover кадрує зображення в квадрат без спотворення. aspect-ratio: 1 / 1 гарантує, що блок залишається квадратним, скільки б широкою не стала колонка сітки.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.