Что может сломать CSS свойство aspect-ratio

alexei12/12/2024 - 08:33
Что может сломать CSS свойство aspect-ratio

В 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 может сломаться или привести к неожиданным результатам? Думаем, еще стоит учитывать фактор поддержки браузерами, но это и так понятно.