Back

Как работает CSS Aspect Ratio

Как работает CSS Aspect Ratio

Вы установили width: 100% на контейнер изображения, но высота схлопывается до нуля до загрузки изображения — вызывая тот самый раздражающий сдвиг макета, который ненавидят пользователи. CSS-свойство aspect-ratio решает эту проблему напрямую, позволяя зарезервировать место для контента до его появления.

Эта статья объясняет, как свойство aspect-ratio участвует в расчётах размеров CSS, чем оно отличается для замещаемых и незамещаемых элементов, и почему оно заменяет старую технику padding-hack для адаптивных макетов.

Ключевые моменты

  • Свойство aspect-ratio определяет предпочтительное соотношение ширины к высоте, которое применяется только когда хотя бы одно измерение установлено как auto.
  • Оно формирует размеры блока элемента, а не медиа внутри него — комбинируйте его с object-fit для управления тем, как изображения или видео заполняют пространство.
  • Оно полностью заменяет устаревший padding-bottom hack, устраняя необходимость в элементах-обёртках, абсолютном позиционировании и непонятных вычислениях.
  • В контексте flexbox и grid следите за взаимодействиями с автоматическим определением размеров, которые могут переопределить или конфликтовать с вычисленными размерами aspect-ratio.

Понимание CSS-свойства Aspect-Ratio

Свойство aspect-ratio определяет предпочтительное соотношение ширины к высоте для блока элемента. Ключевое слово — «предпочтительное» — оно действует только когда хотя бы одно измерение является автоматическим.

.video-container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

Здесь ширина явная (100% от родителя), поэтому браузер вычисляет высоту автоматически, используя соотношение 16:9. Если вы установите и width, и height явно, aspect-ratio обычно не влияет на используемый размер, поскольку определённые размеры имеют приоритет в обычных расчётах макета.

Синтаксис и значения

Свойство принимает три формы:

aspect-ratio: 16 / 9;      /* соотношение ширина / высота */
aspect-ratio: 1;            /* то же, что 1 / 1 (квадрат) */
aspect-ratio: auto 3 / 2;  /* auto с резервным соотношением */

Ключевое слово auto указывает браузеру использовать естественное соотношение сторон элемента, если оно существует. Комбинация auto 3 / 2 означает: использовать естественное соотношение для замещаемых элементов, в противном случае использовать 3/2.

Замещаемые и незамещаемые элементы

Свойство ведёт себя по-разному в зависимости от типа элемента.

Замещаемые элементы (<img>, <video>, <iframe>) имеют внутренние размеры. По умолчанию aspect-ratio: auto использует их естественное соотношение. Когда вы указываете aspect-ratio: auto 16/9, браузер использует естественное соотношение медиа после загрузки, но заранее резервирует место, используя 16/9 — предотвращая сдвиг макета.

Незамещаемые элементы (<div>, <section>) не имеют внутреннего соотношения. Установка aspect-ratio: 1 на <div> с width: 200px создаёт квадрат 200×200. Свойство напрямую контролирует размеры блока.

Aspect-Ratio формирует блок, а не медиа

Критическое различие: aspect-ratio контролирует размеры контейнера, а не то, как медиа заполняет его. Для изображений или видео используйте object-fit для управления поведением медиа внутри блока:

.thumbnail {
  aspect-ratio: 1;
  object-fit: cover;
}

Это создаёт квадратный контейнер, где изображение покрывает область, обрезаясь при необходимости.

CSS Aspect Ratio против Padding Hack

До того, как aspect-ratio получило поддержку браузеров, разработчики использовали трюк с процентным padding-bottom:

/* Устаревший padding hack */
.video-wrapper {
  position: relative;
  padding-bottom: 56.25%; /* 9/16 = 0.5625 */
  height: 0;
}
.video-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Это работает, потому что процентные значения padding вычисляются относительно ширины родителя, создавая высоту на основе соотношения. Но это требует элементов-обёрток, абсолютного позиционирования и непонятной математики.

Современный подход чище:

.video-wrapper {
  aspect-ratio: 16 / 9;
}
.video-wrapper iframe {
  width: 100%;
  height: 100%;
}

Используйте aspect-ratio по умолчанию. Оставляйте padding hack только если вам необходимо поддерживать устаревшие браузеры, такие как IE.

Aspect-Ratio во Flexbox и Grid

Использование aspect-ratio в flexbox и grid макетах работает, но взаимодействия с автоматическим определением размеров могут давать неожиданные результаты.

В CSS Grid aspect-ratio работает естественно с треками автоматического размера:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.grid-item {
  aspect-ratio: 1;
}

Каждый элемент становится квадратным, с высотой, соответствующей его ширине, определённой grid.

Во Flexbox имейте в виду, что flex-grow и flex-shrink влияют на вычисленную ширину, которая затем определяет высоту через aspect-ratio. Если элементы растягиваются неожиданно, проверьте ваши flex-свойства. Установка явного width или flex-basis на элементе даёт aspect-ratio стабильное измерение для работы.

Для обеих систем макетов установите min-height: 0 на элементах, если контент выходит за пределы высоты, ограниченной aspect-ratio.

Практические адаптивные макеты с Aspect-Ratio

Вот распространённый паттерн для адаптивных изображений карточек:

.card-image {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

И для встроенных видео:

.embed-container {
  width: 100%;
  max-width: 800px;
  aspect-ratio: 16 / 9;
}

Оба паттерна резервируют место в макете немедленно, устраняя кумулятивный сдвиг макета (CLS).

Заключение

Свойство aspect-ratio определяет предпочтительное соотношение, используемое когда хотя бы одно измерение является auto. Оно формирует блок элемента — а не медиа-контент — и заменяет технику padding-hack для современных браузеров. При работе с изображениями или видео комбинируйте его с object-fit для управления тем, как медиа заполняет пространство. В контексте flexbox и grid следите за взаимодействиями с автоматическим определением размеров, которые могут влиять на вычисленные размеры.

Часто задаваемые вопросы

Нет. Свойство aspect-ratio действует только когда хотя бы одно измерение является auto. Если вы установите и ширину, и высоту явными значениями, эти размеры имеют приоритет, и объявление aspect-ratio полностью игнорируется.

Установите aspect-ratio с резервным соотношением, например aspect-ratio: auto 4 / 3, чтобы браузер мог зарезервировать место до загрузки изображения. Для лучших результатов и минимального сдвига макета также включите явные атрибуты width и height на элементе img, чтобы браузер сразу знал его внутренние размеры.

Для всех современных браузеров — да. Свойство aspect-ratio поддерживается в Chrome, Firefox, Safari и Edge. Единственная причина сохранять padding-bottom hack — если вам нужно поддерживать Internet Explorer, который вообще не поддерживает aspect-ratio.

Flex-элементы имеют значение min-height: auto по умолчанию, что может предотвратить сжатие элемента ниже высоты его контента. Установите min-height: 0 на flex-элементе, чтобы высота, ограниченная aspect-ratio, соблюдалась. Также проверьте, что flex-grow или flex-shrink не переопределяют ширину, от которой зависит aspect-ratio.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay