Понимание и установка соотношения сторон
Каждый элемент, отображаемый на странице, имеет высоту и ширину, а следовательно, и соотношение сторон, которое представляет собой отношение ширины к высоте. Естественные размеры объекта медиа, то есть его размер без применения масштабирования, изменения размера, масштабирования или границ, известны как его естественный или внутренний размер. Внутренний размер элемента определяется самим элементом, а не применением форматирования, такого как размер рамки, или установкой ширины рамки, отступа или поля.
При разработке сайтов вы часто хотите устанавливать ширину элемента в процентах от размера области просмотра или родительского контейнера и иметь пропорциональное изменение высоты, сохраняя при этом определенное соотношение сторон, в зависимости от размера области просмотра. Для заменяемых элементов, таких как изображения и видео, поддержание определенного соотношения сторон необходимо не только для создания адаптивного веб-дизайна, но и является важным компонентом для обеспечения хорошего пользовательского опыта. Установка соотношения сторон актива предотвращает загрузку подвисаний — сдвигов макета, которые происходят при загрузке медиа после того, как страница уже была отображена, вызывая перерасчет, потому что пространство для актива не было зарезервировано.
С помощью CSS вы можете изменять размер заменяемых и незаменяемых элементов на основе их соотношения сторон. В этом руководстве мы изучим свойство aspect-ratio, обсудим соотношение сторон для заменяемых и незаменяемых элементов, а затем рассмотрим некоторые распространенные случаи использования соотношения сторон.
Как работает свойство aspect-ratio
Значение свойства CSS aspect-ratio определяет предпочтительное соотношение ширины к высоте области элемента. Значение может быть <ratio>, ключевым словом auto, или сочетанием обоих, разделённых пробелами.
<ratio> — это отношение ширины к высоте в указанном порядке. Оно представлено двумя положительными <number> значениями, разделёнными дробной чертой (/) или одним <number>. Когда используется одно число, это то же самое, что запись соотношения в виде <number> / 1, что также равно ширине, делённой на высоту.
Следующие значения являются равнозначными:
aspect-ratio: 3 / 6; aspect-ratio: 1 / 2; aspect-ratio: 0.5 / 1; aspect-ratio: 0.5;
Следующие значения также являются равнозначными:
aspect-ratio: 9/6; aspect-ratio: 3/2; aspect-ratio: 1.5;
Эффект ключевого слова auto зависит от того, является ли элемент, к которому оно применено, заменяемым элементом или нет. Для заменяемых элементов с внутренним соотношением сторон auto означает, что должно использоваться внутреннее соотношение сторон. Во всех остальных случаях значение auto означает, что у области нет предпочтительного соотношения сторон. В обоих случаях это поведение по умолчанию, как если бы свойство aspect-ratio не было применено.
Когда значение содержит как ключевое слово auto, так и значение <ratio>, например, aspect-ratio: auto 2 / 3; или aspect-ratio: 0.75 auto;, значение auto применяется к заменяемым элементам с естественным соотношением сторон, и указанное соотношение width / height или <number> используется в качестве предпочтительного соотношения сторон.
Вы, вероятно, заметили слово «предпочтительное» в определениях выше. Значение aspect-ratio не всегда применяется при установке. Свойство aspect-ratio устанавливает «предпочтительное» соотношение сторон, поэтому оно имеет эффект только в том случае, если хотя бы один из размеров области является автоматическим.
Когда и высота, и ширина или размеры в строке и блоке явно заданы, значение свойства aspect-ratio игнорируется. В этом случае ни один размер не может быть автоматически изменён — предпочтительные размеры явно заданы — поэтому свойство aspect-ratio не имеет эффекта. При указании как размера в строке, так и в блоке, эти значения имеют приоритет.
Для заменяемых элементов, если вы не устанавливаете явно значение (кроме auto) ни для одного из размеров, оба будут по умолчанию установлены на их внутренний размер (любое значение aspect-ratio не применяется). aspect-ratio будет применяться к незаменяемым элементам, у которых размер не задан явно, поскольку незаменяемые элементы либо внутренне, либо внешне заданы по размеру, получая размер из своего содержимого, контейнера, свойств модели области и т.д.
Когда элемент отображается на странице, если CSS не применяется и атрибуты размера HTML не включены, пользовательский агент отобразит объект в его естественном размере.
Изменение соотношения сторон заменяемых элементов
Заменяемые элементы, такие как <img> и <video>, заменяются медиа, которые имеют заданные размеры и, следовательно, внутреннее соотношение сторон. Рассмотрим растровое изображение, например, JPEG, PNG или GIF. Если вы размещаете изображение на странице и не устанавливаете высоту или ширину, либо с помощью атрибутов <img>, либо с помощью CSS, оно будет отображаться в соответствии с его внутренним размером.
Это квадратное изображение 220px, без применения CSS; оно отображается в соответствии с его внутренним или исходным размером.
Если содержимое заменяемого элемента имеет автоматический размер или вы задаёте размер только для одной размерности, например, устанавливая значение для width, браузер автоматически изменит размер другой размерности, в данном случае высоты, сохраняя при этом исходное соотношение сторон медиа.
В этом примере для изображения задана только width, поэтому пользовательский агент сохраняет его соотношение сторон. То же самое изображение повторяется три раза, отображаясь с разной шириной: 55px, 110px, и в соответствии с его естественным размером 220px через значение width: auto.
Только при задании размеров для обеих размерностей существует риск искажения заменяемого элемента. Например, установка width: 100vw; и height: 100vh; для изображения создаёт переменное соотношение сторон; изображение будет отображаться растянутым или сжатым, если соотношение сторон области просмотра отличается от естественного соотношения сторон изображения.
В этом примере то же самое изображение повторяется трижды, с явно заданным одинаковым значением height (110px), но разными значениями width (55px, 110px, и 220px).
Мы намеренно исказили изображения, задав как height, так и width: мы сжали первое и растянули третье.
Мы могли бы создать тот же искажённый эффект, используя свойство CSS aspect-ratio, установив один размер (ни один, ни оба) и задав значение, отличное от 1 (или 1 / 1). Вероятно, этого делать не стоит, но полезно знать, что это возможно.
img {
height: 100vh;
aspect-ratio: 3;
}
Мы задали один размер; 100vh — это полная высота примера <iframe> области просмотра. Для aspect-ratio применения к заменяемым элементам, необходимо задать только один размер. Задание обоих или ни одного размера не работает.
Подгонка заменяемых элементов внутри своих контейнеров
Чтобы подогнать заменяемый элемент под размеры своего контейнера, сохранив при этом его внутреннее соотношение сторон, установите значение свойства object-fit в cover или contain. Это позволит изменить размер заменяемого элемента и либо обрезать его, чтобы он «покрыл» контейнер, либо отобразить его в меньшем размере, полностью «вместив» его в контейнер.
В этом примере квадратное изображение размещается в сетке из трех элементов, каждое из которых имеет соотношение сторон 5 / 2.
Для начала создадим контейнер с тремя элементами, каждый из которых содержит одно изображение:
<div class="grid">
<div>
<img
src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg"
alt="Pride flag" />
</div>
<div>
<img
class="cover"
src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg"
alt="Pride flag" />
</div>
<div>
<img
class="contain"
src="https://mdn.github.io/shared-assets/images/examples/progress-pride-flag.jpg"
alt="Pride flag" />
</div>
</div>
Далее, мы определяем контейнер как сетку, где каждый элемент имеет соотношение сторон 2.5 (5/2) с минимальной шириной 150px. Следовательно, минимальная высота составит 60px. Однако окончательная ширина и высота определяются шириной iframe примера, которая будет зависеть от размера вашего экрана:
.grid {
display: grid;
gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
font-size: 0; /* to minimize whitespace */
}
div div {
aspect-ratio: 5 / 2;
background-color: #ccc;
}
Затем мы задаём размеры изображений и устанавливаем свойство object-fit для последних двух изображений:
img {
height: 100%;
width: 100%;
}
.cover {
object-fit: cover;
}
.contain {
object-fit: contain;
}
Только первое изображение искажено (растянуто). Мы могли бы использовать значение fill в object-fit для создания того же эффекта. Изображение cover занимает всю ширину контейнера, центрируется по вертикали и обрезается для соответствия контейнеру. Значение contain обеспечивает, что изображение помещается в контейнер, центрируется по горизонтали и уменьшается для соответствия.
Определение соотношений сторон для элементов, не являющихся замещаемыми
Хотя соотношение сторон заменяемого элемента сохраняется по умолчанию, изменение размеров не заменяемого элемента обычно изменяет его соотношение сторон. Например, одинаковое содержимое может отображаться как три строки на широкоэкранном или широком родительском контейнере, но как восемь строк на узком экране или контейнере.
В этом примере тот же текст отображается в контейнерах шириной 200px и 600px, а квадрат задан с высотой, соответствующей его ширине 200px:
Чтобы проиллюстрировать проблему задания соотношения сторон элемента, не являющегося замещаемым, с помощью размеров, переключите свойство overflow между auto и visible.
blockquote {
width: 200px;
}
blockquote:nth-of-type(2) {
width: 600px;
}
blockquote:nth-of-type(3) {
height: 200px;
}
Хотя можно задать соотношение сторон для элементов, не являющихся замещаемыми, установив как размеры, так и скрытие переполняемого содержимого, свойство CSS aspect-ratio предоставляет явную поддержку соотношения сторон. Это означает, что можно установить конкретное соотношение сторон даже в том случае, если вы не знаете содержимое или размеры экрана.
В следующем примере мы отображаем квадратные блоки независимо от ширины текста, установив aspect ratio: 1 на <blockquote>, элемент, не являющийся замещаемым:
blockquote {
inline-size: max-content;
aspect-ratio: 1;
}
Каждый блок имеет определён один размер: inline-size, который представляет собой ширину в горизонтальных языках, задан как max-content, что устанавливает размер, равный ширине, необходимой для размещения содержимого без переноса. Второй размер, в данном случае block-size или height, задан такой же длины, как и первый размер. Это достигается свойством aspect-ratio. Мы определили желаемое отношение ширины к высоте элемента блока как 1, что соответствует 1 / 1, то есть квадрату. Это устанавливает направление блока, соответствующее ширине элемента, без использования свойств height или block-size.
В этих примерах размер явно устанавливался на самом элементе. При работе с элементами, не являющимися замещаемыми, соотношение сторон вступает в игру, когда какой-либо размер элемента не задан явно.
Создание круга на основе размера контейнера
Линейный размер блочных элементов, не являющихся замещаемыми, равен размеру области содержимого контейнера aspect-ratio. Поскольку они имеют размер по умолчанию, им не нужно устанавливать явный размер для работы свойства aspect-ratio.
В этом примере у нас есть контейнер <div> шириной 200px, который включает 5px отступа с каждой стороны. Следовательно, линейный размер области содержимого составляет 190px.
Без установки высоты или ширины вложенного элемента <p> мы знаем, что его линейный размер составляет 190px.
С установленным aspect-ratio: 1, абзац будет 190px высотой, если только у него нет видимого переполняющего содержимого, что делает его выше (чего нет).
Высота элемента <div> не задана явно, но он содержит абзац высотой 190px, 5px отступов сверху и снизу и суммарные высоты по умолчанию верхнего и нижнего отступов <p>. В результате он выше, чем шире.
Оба элемента имеют border-radius 50%, поэтому контейнер является овалом, в то время как дочерний элемент, с aspect-ratio 1, но без явного задания линейного или блочного размера, представляет собой круг.
<div><p>Hello world</p></div>
div,
p {
border-radius: 50%;
}
div {
width: 200px;
padding: 5px;
background-color: #66ccff;
}
p {
aspect-ratio: 1;
text-align: center;
border: 10px solid #ffffff;
background-color: #f4aab9;
}
Чтобы сделать <div> кругом, мы можем установить значения height и width одинаковыми или установить aspect-ratio: 1 и установить overflow в auto или hidden. Или же мы можем просто убрать отступы в абзаце с помощью margin-block: 0. Оба варианта показаны ниже.
<section> <div><p>Hello world</p></div> <div><p>Hello world</p></div> <section></section> </section>
div,
p {
aspect-ratio: 1;
border-radius: 50%;
}
div:first-of-type {
overflow: hidden;
}
div:last-of-type p {
margin-block: 0;
}
Общие примеры использования соотношений сторон
Давайте рассмотрим несколько ситуаций, где вы можете использовать соотношение сторон, чтобы решить некоторые общие задачи при создании адаптивных макетов.
Адаптивное оформление внешних ресурсов
Весь контент должен быть адаптивным, даже когда этот контент представляет собой сторонние встраивания, такие как видео с TikTok, YouTube или Instagram. Код, который вы используете для встраивания этих внешних видео, обычно создает <iframe>.
Хотя элемент <video> обычно принимает соотношение сторон своего медиафайла, элементы iframe не обладают этой способностью. Это создаёт проблему обеспечения адаптивности <iframe>, сохраняя при этом соотношение сторон видео, которое он содержит. Один из методов, которые мы можем использовать, — установить ширину iframe на 100% от его контейнера или 100vw для соответствия ширине экрана независимо от её размера. Однако установление фиксированной высоты может растягивать или сжимать видео. Вместо этого мы устанавливаем aspect-ratio на контейнер видео, выравнивая его с таким же соотношением сторон, как у видео. Проблема решена!
Для справки, стандартное соотношение сторон видео YouTube составляет 16:9 при просмотре на настольном компьютере или ноутбуке, в то время как видео TikTok и Instagram имеют соотношение сторон 9:16.
.youtube {
aspect-ratio: 16/9;
}
.instagram,
.tiktok {
aspect-ratio: 9/16;
}
Мы можем использовать функцию aspect-ratio внутри запроса @media вместе со свойством aspect-ratio для изменения размера как iframe, так и видео, которое он содержит. Это гарантирует, что видеоконтент всегда будет максимально возможным — занимая всю ширину или высоту экрана, независимо от размера экрана — при сохранении заданного соотношения сторон.
Мы можем установить видео YouTube с горизонтальной ориентацией, чтобы оно было такой же ширины, как экран, а видео iframe TikTok и Instagram с вертикальной ориентацией, чтобы оно было такой же высоты, как экран. Если соотношение сторон экрана шире 16:9, мы устанавливаем высоту видео YouTube равной высоте экрана. Если соотношение сторон экрана уже 9:16, мы устанавливаем ширину как видео TikTok, так и Instagram равной ширине экрана.
iframe.youtube {
aspect-ratio: 16/9;
width: 100vw;
height: auto;
}
iframe.instagram,
iframe.tiktok {
aspect-ratio: 9/16;
height: 100vh;
width: auto;
}
/* If the viewport is very wide but not very tall */
@media (aspect-ratio > 16 / 9) {
iframe.youtube {
width: auto;
height: 100vh;
}
}
/* If the viewport is very tall but not very wide */
@media (aspect-ratio < 9 / 16) {
iframe.instagram,
iframe.tiktok {
height: auto;
width: 100vw;
}
}
Создание квадратных ячеек сетки
Сетка квадратных ячеек может быть создана путем определения фиксированных размеров дорожек колонок, обеспечивая соответствие размера каждой строки размеру дорожки колонки. Однако при создании адаптивных сеток с использованием auto-fill для размещения как можно большего количества дорожек колонок внутри контейнера ширина каждого элемента становится неопределенной. Это затрудняет определение подходящей высоты для создания квадратных элементов.
Установив соотношение сторон для элементов, мы можем гарантировать, что при выкладке элементов сетки каждый элемент сетки будет такой же высоты, как и ширины, создавая квадратные элементы сетки независимо от размеров контейнера.
В этом примере квадратных элементов сетки дорожки сетки заданы автоматически, принимая свой размер от элементов. Каждый элемент будет иметь ширину не менее 95px , но может быть значительно шире. Независимо от ширины, каждый элемент будет квадратом, а высота будет определяться aspect-ratio для соответствия его ширине.
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(95px, 1fr));
}
.item {
aspect-ratio: 1;
}
Чтобы содержимое элемента сетки не увеличивалось за пределы предпочтительной высоты, заданной aspect-ratio, установите min-height на 0 и overflow на значение, отличное от visible. Это будет работать для содержимого с внутренними размерами. Если у вас есть содержимое, которое по своей природе больше доступного пространства, установите, чтобы это содержимое не превышало размеры элемента сетки, установив max-height (или max-width, в зависимости от содержимого) на 100%.
.item {
min-height: 0;
overflow: auto;
}
.item > * {
max-height: 100%;
}
См. также
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_box_sizing/Understanding_aspect-ratio