В CSS есть свойство aspect-ratio
, которое получило полную поддержку примерно в 2021 году. Это свойство дает гораздо лучший дизайнерский результат, чем принудительное изменение размеров. При использовании элементов вроде <video>
задача "Мне нужен здесь квадрат" или "Мне нужен размер 16:9" - это вполне разумные требования к дизайну. Особенно в нестабильной среде адаптивной верстки, когда вы намеренно стараетесь не думать о точных размерах, потому что знаете, что они могут измениться.
Обычно это просто работает
Вот у нас есть <div>
, помещенный в контейнер. Элемент <div>
естественным образом заполняет всю ширину. Мы задаем для него aspect-ratio: 1 / 1;
, и он стал квадратным.
Следующий пример с видео тоже показателен. В данном случае, по какой-то исторической причине, элемент <video>
по умолчанию имеет ширину 300px, поэтому, если мы хотим, чтобы он заполнял пространство, нам нужно установить свойство width: 100%
, и тогда свойство aspect-ratio
сделает свою работу как нам нужно:
Элементы в сетке также будут вести себя вполне нормально. В следующем примере 12 элементов <div>
расположены в сетке с квадратным соотношением сторон, и они удобно вписываются в нее:
See the Pen Grid Usage of Aspect Ratio by Alexei Goloviznin on CodePen.
Но все может пойти не так, и свойство aspect-ratio
может не сработать оставляя элемент со сломанным соотношением сторон.
Потенциальная ошибка №1 - Установка размеров обоих сторон
Если для элемента заданы и высота height
и ширина width
, то свойство aspect-ratio
игнорируется. Это же касается и block-size
и inline-size
эквивалентов логических свойств.
.el {
inline-size: 300px;
block-size: 200px;
aspect-ratio: 1 / 1; /* ничего не делает */
}
И это вполне имеет смысл (а кто будет его игнорировать?), но это может сильно запутать, если одно из значений размера было задано где-то, где вы этого не ожидали. Например, вы собираетесь задать height
и aspect-ratio
для элемента <img>
, не подозревая, что в базовом файле CSS уже задано значение width
для всех изображений. В этом случае это может привести к неожиданному сбою aspect-ratio
.
Это также может относиться и к данным за пределами CSS. Например, атрибут height
в теге <img>
(который настоятельно рекомендуется использовать) считается здесь другой осью и не позволяет aspect-ratio
работать:
See the Pen Broken Aspect Ratio because of height attribute by Alexei Goloviznin on CodePen.
Ограничение размеров с помощью min-width
, min-height
, min-inline-size
, min-block-size
, max-width
, max-height
, max-block-size
, max-inline-size
будет соблюдаться, и также может нарушить работу aspect-ratio
.
Потенциальная ошибка №2 - Значения типа stretch
В следующем примере у нас есть три элемента <div>
в гибком flex контейнере с разным соотношением сторон. Но… у всех одинаковые размеры:
See the Pen Aspect Ratio in Flexbox Broken (stretching) by Alexei Goloviznin on CodePen.
Но почему?! У этих <div>
задана только ширина, никакой высоты (или ее логических эквивалентов). Проблема же здесь в том, что значение height/block-size задается принудительно, потому что на flex элементы действует значение по умолчанию align-items: stretch;
.
Если же мы изменим в родительском flex контейнере значение по умолчанию на align-items: flex-start;
, то увидим, что свойство aspect-ratio
начнёт работать:
See the Pen Aspect Ratio in Flexbox Working by Alexei Goloviznin on CodePen.
Это относиться к любому из значений типа stretch в CSS сетке или flexbox. Например, если в CSS сетке есть свойство justify-items: stretch
, то данная проблема также может проявиться.
Потенциальная ошибка №3 – Содержимое, которое задает высоту
Раньше, чтобы устанавливать соотношение сторон, мы использовали старый трюк с отступами. Он заключался в том, что с помощью padding-bottom
создавалось пространство в блоке нулевой высоты. Процентное значение для отступа - это процент от ширины, таким образом устанавливается связь между шириной и высотой. Но затем внутри этого блока мы помещаем блок с абсолютным позиционированием. Проблема с абсолютным позиционированием здесь заключается в том, что содержимое этого блока находится вне обычного потока документа. Так что если, например, вы поместите внутрь него текст, который будет выше блока, у вас возникнет проблема. Ниже можно наблюдать пример того, как содержимое выходит за пределы блока. У блока правильное соотношение сторон, но вряд ли это желаемый результат:
See the Pen Problem with Padded Box by Alexei Goloviznin on CodePen.
Если же вместо этого для нашего блока мы будем использовать aspect-ratio
, то мы получим:
See the Pen Aspect Ratio Busted with Content by Alexei Goloviznin on CodePen.
Теперь оранжевый блок содержит всё содержимое, что, вероятно, и является желаемым результатом в большинстве ситуаций. Но, что примечательно, у блока больше не установлены соотношения сторон, как мы декларировали.
Что еще мы упустили из того, что aspect-ratio
может сломаться или привести к неожиданным результатам? Думаем, еще стоит учитывать фактор поддержки браузерами, но это и так понятно.