Главная » Статьи » Соотношение сторон это круто

Соотношение сторон это круто

Соотношение сторон это круто

От автора: мне одному кажется, что большую часть времени изучение новых возможностей CSS приводит к изучению не только принципа работы одного конкретного свойства, а набора свойств и того, как они работают вместе? А порой и изучения всей спецификации. Нет, я не жалуюсь: понятное дело, что свойства нужно рассматривать как часть экосистемы. Но признаюсь, я обожаю, когда новое CSS свойство появляется в браузерах, и его изучение не требует много сил, и все просто работает.

Свойство aspect-ratio отвечает всем этим требованиям и решает все глупые костыли (соотношение сторон) одной строкой. Свойство поддерживается уже год, но уверенно его использовать мы смогли только после релиза для Safari в сентябре 2021.

Padding хак, прощай

Раньше для соблюдения элементами соотношения сторон нам нужно было писать довольно страшный CSS:

.aspect-box { position: relative;
} .aspect-box::before { display: block; content: ''; width: 100%; padding-bottom: calc(100% / (var(--aspect-ratio, 3 / 2)));
} .aspect-box > :first-child { position: absolute; top: 0; right: 0; bottom: 0; left: 0;
}

Этот способ назывался паддинг хак потому что, ну, он именно это и делает. Кастомное свойство отрезает повторение на случай, если нужно более одного соотношения сторон. Никто в здравом уме не хочет писать так. С помощью Ratio Buddy можно сгенерировать Sass сниппет.

Практическое использование aspect-ratio

Работа с aspect-ratio гораздо проще: указываете ширину и высоту соотношения сторон через слэш или укажите число с плавающей точкой. 2 примера соотношения сторон ниже работают одинаково:

.aspect-box { aspect-ratio: 3 / 2;
} .aspect-box { aspect-ratio: 1.5;
}

Ширину и высоту можно явно указать для элемента, и aspect-ratio будет работать ровно так, как вы ожидаете: если какое-то разрешение не указано, оно автоматически определится по соотношению сторон. Если указать для ширины и высоты не auto, то соотношение сторон больше не применяется. Это не баг. Так и задумано, это удобно.

Демонстрация

Увеличение размеров элемента и подстройка под содержимое

aspect-ratio умеет изменять размер относительно дочерних элементов и родительских. Это значит, что он подстраивается как под контент, так и под контекст. Все 3 блока ниже имеют соотношение сторон 2 / 1 и явно заданную ширину. Текст в третьем блоке не помещается, из-за чего блок вертикально расширяется, подстраиваясь под контент.

Соотношение сторон это круто

Демонстрация

Если вместо ширины явно указать высоту, то элемент не будет расширяться. Вместо этого текст выйдет за пределы элемента (можно поправить с помощью свойства overflow).

Соотношение сторон это круто

Демонстрация

Соотношение сторон изображений и object-fit

Сила aspect-ratio раскрывается при работе изменении размеров изображений в сочетании с object-fit. С помощью object-fit: cover можно создать превью как для галереи изображений:

Демонстрация

Или можно использовать object-fit: contain для сетки логотипов.

Демонстрация

Нужно добавить, что object-fit обязательно требует явно заданной ширины и высоты элемента, чтобы «подогнать» размеры. Разберем разметку ниже (изображение внутри блока с соотношением сторон):

<div class="aspect-box"> <img src="https://images.unsplash.com/photo..." alt="Robin on a log" />
</div>

Чтобы изображение целиком заполнило родительский блок, необходимо написать следующие стили:

img { display: block; width: 100%; height: 100%; object-fit: cover;
}

Довольно часто требуется поместить что-то в блок с соотношением сторон, как выше. Однако блок-обертку можно было опустить и добавить свойство aspect-ratio прямо на изображение вместо height или width:

img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover;
}

Блоки с соотношением сторон в контексте

В демо выше для галереи используется Grid или Flexbox. Все работает, как и ожидается. А что есть у нас сетка, внутри которой блоки с соотношением сторон? А в блоках только текст, или они вообще пустые. Нам стоит обратить внимание на то, что FlexBox и Grid по умолчанию задают align-items: stretch. То есть если у нас в сетки есть одна ячейка с контентом, которые не помещается в соотношение сторон, то другие ячейки начнут увеличивать высоту, равняясь на самый длинный элемент и игнорируя соотношение сторон (предполагается, что для ячеек явно задана ширина, а не высота, так как это более частый сценарий):

Соотношение сторон это круто

Для нашего дизайна поведение ожидаемое и часто подходящее по умолчанию. Но если мы все же хотим соблюдать соотношение сторон ячеек, даже если один элемент в ряду выше остальных, то нам необходимо указать другое значение для align-items, отличное от значения по умолчанию для Grid и Flexbox контейнера:

Соотношение сторон это круто

Демонстрация

Минимальное соотношение сторон

Есть место, где стандартное поведение полезно. Когда в нашем UI компоненте есть текст с одной стороны и изображений с другой. Например, CTA элемент (элемент призывающий к действию). Если к изображению добавить соотношение сторон, то колонка с текстом будет такой же высоты, что и высота изображения. А если текст не будет помещаться в свой блок, то уже изображение будет увеличиваться для соблюдения высоты блока с текстом.

Соотношение сторон это круто

Демонстрация

В этом примере aspect-ratio ведет себя не как фиксированное значение, а как «минимальное».

Поддержка в браузерах

Сейчас поддержка хорошая. В большинстве случаев не придется городить фолбэки. Пользователи все так же увидят ваш контент. Просто он не будет идеально соблюдать желаемое соотношение сторон. Однако в случае с галереей изображений на object-fit любое большое изображение приведет к тому, что все превьюшки в ряду увеличатся, из-за чего изображения могут неудачно обрезаться.

Соотношение сторон это круто

Проблему можно пофиксить, если на grid контейнер добавить align-items: start.

Соотношение сторон это круто

Если вам нужно предоставить запасной вариант для старых браузеров, то достаточно старого доброго функционального запроса:

.aspect-box { /* Styles for browsers that don't support aspect-ratio */
} @supports (aspect-ratio: 1 / 1) { .aspect-box { /* Styles for browsers that support aspect-ratio */ }
}

Заключение

aspect-ratio – яркий пример скромного свойства, которое решает старые проблемы с CSS. Его просто использовать, и оно ведет себя соответственно контента. Никакой лишний CSS не нужен.

Автор: Michelle Barker

Источник: css-irl.info

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен