Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «CSS співвідношення сторін». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`aspect-ratio`**, це CSS властивість, що фіксує співвідношення ширини до висоти. Браузер автоматично обчислює розмір, якого не вистачає. ```css .video { width: 100%; aspect-ratio: 16 / 9; /* висота = ширина * (9/16). При 800px ширини: 450px висота */ } ``` **Головне правило:** задай лише один розмір. Якщо задані і `width`, і `height`, ratio ігнорується.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`aspect-ratio`**, це CSS властивість, що автоматично обчислює висоту елемента з його ширини (або навпаки) за фіксованим співвідношенням. ## Теорія ### TL;DR - Як рамка для фото, що підлаштовує висоту під будь-яку ширину без спотворень. Ти задаєш пропорцію, браузер рахує. - До 2021 року: трюк з `padding-bottom: 56.25%` на div-обгортці. Тепер одна властивість замінює все це. - Задай один розмір (ширину або висоту) плюс `aspect-ratio`, браузер обчислить інший. - Пропускай, якщо обидва розміри вже задані явно. ### Швидкий приклад ```css .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:** ```css /* Неправильно - 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` з `@supports` fallback для старих браузерів - **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. ```html <div class="video-wrapper"> <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" style="width: 100%; height: 100%; border: none;" allowfullscreen> </iframe> </div> ``` ```css .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` обробляє кадрування. ```css .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` гарантує, що блок залишається квадратним, скільки б широкою не стала колонка сітки.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.