Поддерживать соотношение сторон div с помощью CSS

Я хочу создать div это может изменить его ширину / высоту при изменении ширины окна.

Существуют ли какие-либо правила CSS3, которые позволили бы изменить высоту в соответствии с шириной при сохранении соотношения сторон?

Я знаю, что могу сделать это с помощью JavaScript, но я бы предпочел использовать только CSS.

40 ответов

Решение

Просто создайте обертку <div> с процентным значением для padding-bottom, как это:

div {
  width: 100%;
  padding-bottom: 75%;
  background: gold; /** <-- For the demo **/
}
<div></div>

Это приведет к <div> с высотой, равной 75% ширины контейнера (соотношение сторон 4:3).

Это зависит от того, что для заполнения:

Процент рассчитывается относительно ширины блока, содержащего сгенерированный блок [...] (источник: w3.org, выделение шахты)

Значения отступов для других форматов изображения и ширины 100%:

aspect ratio  | padding-bottom value
--------------|----------------------
    16:9      |       56.25%
    4:3       |       75%
    3:2       |       66.66%
    8:5       |       62.5%

Размещение контента в div:

Чтобы сохранить соотношение сторон div и предотвратить растяжение его содержимого, вам нужно добавить абсолютно позиционированный дочерний элемент и растянуть его по краям оболочки с помощью:

div.stretchy-wrapper {
  position: relative;
}

div.stretchy-wrapper > div {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
}

Вот демо и еще одна более глубокая демонстрация

vw единицы:

Ты можешь использовать vw единицы для ширины и высоты элемента. Это позволяет сохранить соотношение сторон элемента в зависимости от ширины области просмотра.

vw: 1/100 ширины области просмотра. [ MDN ]

Кроме того, вы также можете использовать vh для высоты окна просмотра, или даже vmin / vmax использовать меньшее / большее из размеров области просмотра (обсуждение здесь).

Пример: соотношение сторон 1:1

div {
  width: 20vw;
  height: 20vw;
  background: gold;
}
<div></div>

Для других соотношений сторон вы можете использовать следующую таблицу для расчета значения высоты в соответствии с шириной элемента:

aspect ratio  |  multiply width by
-----------------------------------
     1:1      |         1
     1:3      |         3
     4:3      |        0.75
    16:9      |       0.5625

Пример: 4x4 сетка квадратных делений

body {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
div {
  width: 23vw;
  height: 23vw;
  margin: 0.5vw auto;
  background: gold;
}
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>

Вот Скрипка с этой демонстрацией, и вот решение, чтобы сделать отзывчивую сетку квадратов с вертикально и горизонтально центрированным содержанием.


Поддержка браузеров для блоков vh/vw - IE9+, см. CanIuse для получения дополнительной информации

Решение 2021 года - используйте aspect-ratio CSS свойство

(в настоящее время поддерживается в Chromium, Safari Technology Preview и Firefox Nightly)

      <div class='demo'></div>
      .demo {
  background: black;
  width: 500px;
  aspect-ratio: 4/3;
}

Я наткнулся на умное решение, используя <svg> а также display:grid,

Элемент сетки позволяет вам занимать одно и то же пространство с двумя (или более) элементами, без необходимости указывать, какой из них устанавливает высоту. Что означает, что из коробки, более высокий устанавливает соотношение.

Это означает, что вы можете использовать его как есть, когда вы знаете, что контент никогда не будет достаточно высоким, чтобы заполнить весь "коэффициент", и вы просто ищете способ расположить контент в этом пространстве (то есть, чтобы центрировать его в обоих направлениях, используйте display:flex; align-items:center; justify-content:center).
Это почти так же, как использование прозрачного <img> с display:block и заданное соотношение, кроме <svg> легче и значительно легче изменить (чтобы изменить соотношение в случае необходимости).

<div class="ratio">
  <svg viewBox="0 0 1 1"></svg>
  <div>
    I'm square
  </div>
</div>
.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

Все, что вам нужно сделать, это изменить <svg> соотношение s:

  • <svg viewBox="0 0 4 3"></svg>
  • <svg viewBox="0 0 16 9"></svg>

Посмотрите, как это работает:

.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

/* below code NOT needed for setting the ratio 
 * I just wanted to mark it visually
 * and center contents
 */
.ratio div {
  border: 1px solid red;
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="ratio">
  <svg viewBox="0 0 7 1"></svg>
  <div>
    Fixed ratio 7:1
  </div>
</div>


Если вам нужно решение, в котором элементу контента не разрешено устанавливать соотношение, когда оно выше (со скрытым или автоматическим переполнением), вам нужно установить position:relative на сетке и position:absolute; height:100%; overflow-y: auto; на содержание. Пример:

.ratio {
  display: grid;
  position: relative;
}
.ratio > * {
  grid-area: 1/1/1/1;
}


.ratio > div {
  height: 100%;
  overflow-y: auto;
  position: absolute;
  
  /* the rest is not needed */
  border: 1px solid red;
  padding: 0 1rem;
}
<div class="ratio">
  <svg viewBox="0 0 7 1"></svg>
  <div>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. A scelerisque purus semper eget. Sem nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. A cras semper auctor neque vitae tempus quam pellentesque nec. Morbi enim nunc faucibus a pellentesque sit amet porttitor. Arcu odio ut sem nulla. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida neque. Cras tincidunt lobortis feugiat vivamus at augue eget. Laoreet sit amet cursus sit amet. Amet nulla facilisi morbi tempus iaculis urna id volutpat. Leo in vitae turpis massa sed elementum tempus egestas sed. Egestas integer eget aliquet nibh. Dolor sit amet consectetur adipiscing elit.

<p>Ut aliquam purus sit amet. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Diam in arcu cursus euismod quis viverra nibh. Nullam vehicula ipsum a arcu cursus vitae congue. Vel orci porta non pulvinar neque laoreet suspendisse. At tellus at urna condimentum mattis pellentesque. Tristique senectus et netus et malesuada. Vel pretium lectus quam id leo in. Interdum velit euismod in pellentesque. Velit euismod in pellentesque massa placerat duis. Vitae suscipit tellus mauris a diam maecenas sed enim.

<p>Mauris a diam maecenas sed enim ut sem. In hendrerit gravida rutrum quisque. Amet dictum sit amet justo donec enim diam. Diam vulputate ut pharetra sit amet aliquam id. Urna porttitor rhoncus dolor purus non enim praesent. Purus in massa tempor nec feugiat nisl pretium. Sagittis vitae et leo duis ut. Facilisi nullam vehicula ipsum a arcu cursus vitae congue mauris. Volutpat odio facilisis mauris sit amet massa vitae tortor condimentum. Aliquam purus sit amet luctus venenatis lectus magna. Sit amet purus gravida quis blandit turpis. Enim eu turpis egestas pretium aenean. Consequat mauris nunc congue nisi. Nunc sed id semper risus in hendrerit gravida rutrum. Ante metus dictum at tempor. Blandit massa enim nec dui nunc mattis enim ut.
  </div>
</div>

Я нашел способ сделать это с помощью CSS, но вы должны быть осторожны, так как он может меняться в зависимости от потока вашего собственного веб-сайта. Я сделал это для того, чтобы встроить видео с постоянным соотношением сторон в часть ширины моего веб-сайта.

Скажем, у вас есть встроенное видео, как это:

<object>
     <param ... /><param ... />...
     <embed src="..." ...</embed>
</object>

Затем вы можете поместить все это в div с помощью класса "video". Этот класс видео, вероятно, будет плавным элементом на вашем веб-сайте, так что сам по себе он не имеет прямых ограничений по высоте, но при изменении размера браузера он будет меняться по ширине в зависимости от потока веб-сайта. Это был бы элемент, который вы, вероятно, пытаетесь вставить встраиваемое видео, сохраняя при этом определенное соотношение сторон видео.

Чтобы сделать это, я поместил изображение перед внедренным объектом внутри div класса "video".

!!! Важной частью является то, что изображение имеет правильное соотношение сторон, которое вы хотите сохранить. Кроме того, убедитесь, что размер изображения по крайней мере такой же большой, как и наименьшее, на которое вы ожидаете, что видео (или то, что вы поддерживаете AR) будет получено в зависимости от вашего макета. Это позволит избежать возможных проблем с разрешением изображения при изменении его размера в процентах. Например, если вы хотите сохранить соотношение сторон 3:2, не просто используйте изображение размером 3 на 2 пикселя. Это может работать при некоторых обстоятельствах, но я не проверял это, и это, вероятно, было бы хорошей идеей, чтобы избежать.

Вы, вероятно, уже должны иметь минимальную ширину, подобную этой, определенной для плавных элементов вашего веб-сайта. Если нет, то это хорошая идея, чтобы избежать обрезания элементов или их наложения, когда окно браузера становится слишком маленьким. В какой-то момент лучше иметь полосу прокрутки. Наименьшая ширина, которую должна получить веб-страница, составляет около 600 пикселей (включая столбцы фиксированной ширины), потому что разрешение экрана не уменьшается, если вы не имеете дело с сайтами, удобными для телефона.!!!

Я использую полностью прозрачный PNG, но я не думаю, что это в конечном итоге имеет значение, если вы делаете это правильно. Как это:

<div class="video">
     <img class="maintainaspectratio" src="maintainaspectratio.png" />
     <object>
          <param ... /><param ... />...
          <embed src="..." ...</embed>
     </object>
</div>

Теперь вы сможете добавить CSS, похожий на следующий:

div.video { ...; position: relative; }
div.video img.maintainaspectratio { width: 100%; }
div.video object { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
div.video embed {width: 100%; height: 100%; }

Убедитесь, что вы также удалили любое явное объявление высоты или ширины внутри объекта и вставили теги, которые обычно идут с кодом вставки для копирования / вставки.

Как это работает, зависит от свойств позиции элемента класса видео и элемента, который вы хотите, чтобы поддерживать определенное соотношение сторон. Он использует то, как изображение будет сохранять правильное соотношение сторон при изменении размера элемента. Он сообщает всему, что находится в элементе видео класса, чтобы в полной мере воспользоваться недвижимостью, обеспечиваемой динамическим изображением, увеличивая его ширину / высоту до 100% элемента видео класса, настраиваемого изображением.

Довольно круто, а?

Возможно, вам придется немного поиграть с этим, чтобы заставить его работать с вашим собственным дизайном, но на самом деле это работает на удивление хорошо для меня. Общая концепция есть.

Эллиот вдохновил меня на это решение - спасибо:

aspectratio.png это полностью прозрачный PNG-файл с размером вашего предпочтительного соотношения сторон, в моем случае 30x10 пикселей.

HTML

<div class="eyecatcher">
  <img src="/img/aspectratio.png"/>
</div>

CSS3

.eyecatcher img {
  width: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url(../img/autoresized-picture.jpg);
}

Пожалуйста, обратите внимание: background-size это функция css3, которая может не работать с вашими целевыми браузерами Вы можете проверить совместимость (например, на http://caniuse.com/).

Как @web-tiki уже показывают способ использования vh/vwМне также нужен способ центрирования на экране, вот фрагмент кода для портрета 9:16.

.container {
  width: 100vw;
  height: calc(100vw * 16 / 9);
  transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}

translateY будет держать этот центр на экране. calc(100vw * 16 / 9) Ожидаемая высота для 9/16.(100vw * 16 / 9 - 100vh) высота перелива, так что потяните вверх overflow height/2 будет держать его в центре экрана.

Для пейзажа, и держите 16: 9, вы показываете использование

.container {
  width: 100vw;
  height: calc(100vw * 9 / 16);
  transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}

Соотношение 9/16 легко изменить, не нужно заранее 100:56.25 или же 100:75. Если вы хотите в первую очередь обеспечить высоту, вам следует переключить ширину и высоту, например: height:100vh;width: calc(100vh * 9 / 16) для 9:16 портрет.

Если вы хотите адаптировать для другого размера экрана, вы также можете заинтересовать

  • фоновый размер обложки / содержит
    • Выше стиль похож на содержание, зависит от соотношения ширина: высота.
  • Объект посадки
    • обложка / содержание для тега img/video
  • @media (orientation: portrait)/@media (orientation: landscape)
    • Медиа-запрос для portrait/landscape изменить соотношение.

Как указано здесь на w3schools.com и несколько раз подтверждено в этом принятом ответе, значения заполнения в процентах (выделено мной):

Определяет отступ в процентах от ширины содержащего элемента

Итак, правильный пример адаптивного DIV, который поддерживает соотношение сторон 16:9, выглядит следующим образом:

CSS

.parent {
    position: relative;
    width: 100%;
}
.child {
    position: relative;
    padding-bottom: calc(100% * 9 / 16);
}
.child > div {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

HTML

<div class="parent">
    <div class="child">
        <div>Aspect is kept when resizing</div>
    </div>
</div>

Демо на JSFiddle

Чтобы добавить к ответу Web_Designer, <div> будет иметь высоту (полностью составленную из нижнего отступа) 75% ширины содержащего его элемента. Вот хорошее резюме: http://mattsnider.com/css-using-percent-for-margin-and-padding/. Я не уверен, почему так должно быть, но так оно и есть.

Если вы хотите, чтобы ваш div был шириной, отличной от 100%, вам нужен еще один упаковочный div, для которого нужно установить ширину:

div.ar-outer{
    width: 60%; /* container; whatever width you want */
    margin: 0 auto; /* centered if you like */
}
div.ar {
    width:100%; /* 100% of width of container */
    padding-bottom: 75%; /* 75% of width of container */
    position:relative;
}
div.ar-inner {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
}

Недавно я использовал что-то похожее на трюк с изображением Эллиота, чтобы позволить мне использовать медиазапросы CSS для обслуживания другого файла логотипа в зависимости от разрешения устройства, но все равно пропорционально масштабировать как <img> будет естественно (я установил логотип в качестве фонового изображения для прозрачного.png с правильным соотношением сторон). Но решение Web_Designer спасло бы меня запрос http.

Что ж, недавно мы получили возможность использовать aspect-ratio свойство в CSS.

https://twitter.com/Una/status/1260980901934137345/photo/1

Примечание: поддержка пока не самая лучшая...

https://caniuse.com/

Это улучшение принятого ответа:

  • Использует псевдоэлементы вместо div-оболочки
  • Соотношение сторон основано на ширине поля вместо его родителя
  • Коробка будет растягиваться вертикально, когда содержимое станет выше

.box {
  margin-top: 1em;
  margin-bottom: 1em;
  background-color: #CCC;
}

.fixed-ar::before {
  content: "";
  float: left;
  width: 1px;
  margin-left: -1px;
}
.fixed-ar::after {
  content: "";
  display: table;
  clear: both;
}

.fixed-ar-16-9::before {
  padding-top: 56.25%;
}
.fixed-ar-3-2::before {
  padding-top: 66.66%;
}
.fixed-ar-4-3::before {
  padding-top: 75%;
}
.fixed-ar-1-1::before {
  padding-top: 100%;
}

.width-50 {
  display: inline-block;
  width: 50%;
}
.width-20 {
  display: inline-block;
  width: 20%;
}
<div class="box fixed-ar fixed-ar-16-9">16:9 full width</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-3-2 width-20">3:2</div>
<div class="box fixed-ar fixed-ar-4-3 width-20">4:3</div>
<div class="box fixed-ar fixed-ar-1-1 width-20">1:1</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>

На самом деле, получивший большое количество голосов ответ - очень хорошее решение, но есть новая функция CSS, имя которой aspect-ratio.

Его можно было использовать так:

      .someClass {
  width: 100%;
  aspect-ratio: 4/3;
}

Он автоматически определяет его высоту, но смотрите таблицу совместимости:

Если поддержка браузера важна для вашего проекта, не используйте его. использовать padding-bottom техника.

Вы можете использовать SVG. Сделайте положение контейнера / оболочки относительным, сначала поместите svg как статически расположенное, а затем поместите абсолютно позиционированное содержимое (вверху: 0; слева: 0; справа: 0; внизу:0;)

Пример с пропорциями 16:9:

image.svg: (может быть встроено в src)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 9" width="16" height="9"/>

CSS:

.container {
  position: relative;
}
.content {
  position: absolute;
  top:0; left:0; right:0; bottom:0;
}

HTML:

<div class="container">
  <img style="width: 100%" src="image.svg" />
  <div class="content"></div>
</div>

Обратите внимание, что встроенный svg, похоже, не работает, но вы можете urlencode svg и встроить его в атрибут img src следующим образом:

<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2016%209%22%20width%3D%2216%22%20height%3D%229%22%2F%3E" style="width: 100%;" />

SCSS - лучшее решение в моем случае; используя атрибут данных:

[data-aspect-ratio] {
    display: block;
    max-width: 100%;
    position: relative;

    &:before {
        content: '';
        display: block;
    }

    > * {
        display: block;
        height: 100%;
        left: 0;
        position: absolute;
        top: 0;
        width: 100%;
    }
}
[data-aspect-ratio="3:1"]:before {
    padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
    padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
    padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
    padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
    padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
    padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
    padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
    padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
    padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
    padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
    padding-top: 300%;
}

Например:

<div data-aspect-ratio="16:9"><iframe ...></iframe></div>

источник

Решение 2020 - использование сетки и отступов псевдоэлемента

Я нашел более свежий способ решить этот случай. Это решение является потомком любогоpadding-bottom метод, но без всяких position: absolute дети, просто используя display: grid; и псевдоэлемент.

Здесь у нас есть .ratio::before со старым добрым padding-bottom: XX% а также grid-area: 1 / 1 / 1 / 1;, что заставляет псевдоэлемент сохранять позицию в сетке. Хотя здесь у нас естьwidth: 0; чтобы предотвратить переполнение этим основным элементом (мы холодно используем z-index здесь, но этот короче).

И наш главный элемент .ratio > *:first-child занимает такое же положение, как .ratio::before, который grid-area: 1 / 1 / 1 / 1;, поэтому они оба занимают одно и то же место в ячейке сетки. Теперь мы можем поместить любое содержимое в наш div, и псевдоэлемент определяет соотношение ширины / высоты. Подробнее о грид-области.

.ratio {
  display: grid;
  grid-template-columns: 1fr;
  max-width: 200px; /* just for instance, can be 100% and depends on parent */  
}

.ratio::before {
  content: '';
  width: 0;
  padding-bottom: calc(100% / (16/9)); /* here you can place any ratio */
  grid-area: 1 / 1 / 1 / 1;
}

.ratio>*:first-child {
  grid-area: 1 / 1 / 1 / 1; /* the same as ::before */
  background: rgba(0, 0, 0, 0.1); /* just for instance */
}
<div class="ratio">
  <div>16/9</div>
</div>


Хотя вы можете использовать CSS val и поместить свое соотношение в HTML, используя styleатрибут. Работает сdisplay: inline-grid также.

.ratio {
  display: inline-grid;
  grid-template-columns: 1fr;
  width: 200px; /* just for instance, can be 100% and depends on parent */ 
  margin-right: 10px; /* just for instance */
}

.ratio::before {
  content: '';
  width: 0;
  padding-bottom: calc(100% / (var(--r))); /* here you can place any ratio */
  grid-area: 1 / 1 / 1 / 1;
}

.ratio>*:first-child {
  grid-area: 1 / 1 / 1 / 1; /* the same as ::before */
  background: rgba(0, 0, 0, 0.1); /* just for instance */
}
<div class="ratio" style="--r: 4/3;">
  <div>4/3</div>
</div>

<div class="ratio" style="--r: 16/9;">
  <div>16/9</div>
</div>

Основываясь на ваших решениях, я сделал несколько хитростей:

Когда вы используете его, ваш HTML будет только

<div data-keep-ratio="75%">
    <div>Main content</div>
</div>

Чтобы использовать его таким образом, сделайте: CSS:

*[data-keep-ratio] {
    display: block;
    width: 100%;
    position: relative;
}
*[data-keep-ratio] > * {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

и JS (JQuery)

$('*[data-keep-ratio]').each(function(){ 
    var ratio = $(this).data('keep-ratio');
    $(this).css('padding-bottom', ratio);
});

И имея это, вы просто установите attr data-keep-ratio в высоту / ширину и все.

Хотя большинство ответов очень крутые, большинство из них требуют правильного размера изображения... Другие решения работают только на ширину и не заботятся о доступной высоте, но иногда вы также хотите разместить контент на определенной высоте.,

Я попытался соединить их вместе, чтобы создать полностью переносимое и масштабируемое решение... Хитрость заключается в том, чтобы использовать автоматическое масштабирование изображения, но использовать встроенный элемент SVG вместо использования предварительно отрендеренного изображения или любой другой формы. второй HTTP-запрос...

div.holder{
  background-color:red;
  display:inline-block;
  height:100px;
  width:400px;
}
svg, img{
  background-color:blue;
  display:block;
  height:auto;
  width:auto;
  max-width:100%;
  max-height:100%;
}
.content_sizer{
  position:relative;
  display:inline-block;
  height:100%;
}
.content{
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:0;
  background-color:rgba(155,255,0,0.5);
}
<div class="holder">
  <div class="content_sizer">
    <svg width=10000 height=5000 />
    <div class="content">
    </div>
  </div>
</div>

Обратите внимание, что я использовал большие значения в атрибутах SVG ширины и высоты, так как он должен быть больше максимального ожидаемого размера, поскольку он может только уменьшаться. В примере соотношение div составляет 10:5.

Если вы хотите разместить квадрат внутри видового экрана в книжной или альбомной ориентации (настолько большой, насколько это возможно, но ничего не торчит снаружи), переключайтесь между vw/vh по ориентации portrait/landscape:

@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
} 
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
} 

Вы можете добиться этого с помощью SVG.

Это зависит от случая, но в некоторых это действительно полезно. В качестве примера - вы можете установитьbackground-image без установки фиксированной высоты или использовать его для встраивания YouTube <iframe> с соотношением 16:9 а также position:absolute и т.п.

За 3:2 набор соотношений viewBox="0 0 3 2" и так далее.

Пример:

div{
    background-color:red
}
svg{
    width:100%;
    display:block;
    visibility:hidden
}

.demo-1{width:35%}
.demo-2{width:20%}
<div class="demo-1">
  <svg viewBox="0 0 3 2"></svg>
</div>

<hr>

<div class="demo-2">
  <svg viewBox="0 0 3 2"></svg>
</div>

Допустим, у вас есть 2 div, внешний div это контейнер, а внутренним может быть любой элемент, который вам нужен, чтобы сохранить его соотношение (img или iframe на youtube или что-то еще)

HTML выглядит так:

<div class='container'>
  <div class='element'>
  </div><!-- end of element -->

Допустим, вам нужно сохранить соотношение "элемент"

соотношение => 4 к 1 или 2 к 1 ...

CSS выглядит так

.container{
  position: relative;
  height: 0
  padding-bottom : 75% /* for 4 to 3 ratio */ 25% /* for 4 to 1 ratio ..*/

}

.element{
  width : 100%;
  height: 100%;
  position: absolute; 
  top : 0 ;
  bottom : 0 ;
  background : red; /* just for illustration */
}

заполнение, если указано в%, рассчитывается на основе ширины, а не высоты... так что, в принципе, вам не важно, какая у вас ширина, высота будет всегда рассчитываться исходя из этого. который будет держать соотношение.

Я хотел бы поделиться своим решением, где у меня есть img -помечать заполнение определенного соотношения сторон. Я не мог использовать background из-за отсутствия поддержки CMS, и я бы не предпочел использовать тег стиля, например: <img style="background:url(...)" />, Кроме того, ширина составляет 100%, поэтому не нужно устанавливать фиксированный размер, как в некоторых решениях. Это будет масштабироваться ответственно!

.wrapper {
  width: 50%;
}

.image-container {
  position: relative;
  width: 100%;
}

.image-container::before {
  content: "";
  display: block;
}

.image-container img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ratio-4-3::before {
  padding-top: 75%;
}

.ratio-3-1::before {
  padding-top: calc(100% / 3);
}

.ratio-2-1::before {
  padding-top: 50%;
}
<div class="wrapper"> <!-- Just to make things a bit smaller -->
  <p>
  Example of an 4:3 aspect ratio, filled by an image with an 1:1 ratio.
  </p>
  <div class="image-container ratio-4-3"> <!-- Lets go for a 4:3 aspect ratio -->
    <img src="https://placekitten.com/1000/1000/" alt="Kittens!" />
  </div>
  <p>
  Just place other block elements around it; it will work just fine.
  </p>
</div>

Я сталкивался с этой проблемой довольно много раз, поэтому я сделал для нее решение JS. Это в основном регулирует высоту domElement в соответствии с шириной элемента в соответствии с указанным соотношением. Вы можете использовать его следующим образом:

<div ratio="4x3"></div>

Имейте в виду, что, поскольку он устанавливает высоту элемента, элемент должен быть display:block или же display:inline-block,

https://github.com/JeffreyArts/html-ratio-component

Простой способ сохранить соотношение сторон с помощью элемента холста.

Попробуйте изменить размер div ниже, чтобы увидеть его в действии.

Для меня этот подход работал лучше всего, поэтому я делюсь им с другими, чтобы они тоже могли извлечь из него пользу.

.cont {
  border: 5px solid blue;
  position: relative;
  width: 300px;
  padding: 0;
  margin: 5px;
  resize: horizontal;
  overflow: hidden;
}

.ratio {
  width: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

Также работает с динамической высотой!

.cont {
  border: 5px solid blue;
  position: relative;
  height: 170px;
  padding: 0;
  margin: 5px;
  resize: vertical;
  overflow: hidden;
  display: inline-block; /* so the div doesn't automatically expand to max width */
}

.ratio {
  height: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

Новым в Chrome 88, а вскоре и в других браузерах, является новый CSS. <tcode id="254504"></tcode> свойство.

Свойство CSS ratio-ratio устанавливает предпочтительное соотношение сторон для поля, которое будет использоваться при вычислении автоматических размеров и некоторых других функциях компоновки.

<strong>Статья о хитростях CSS</strong>

<strong>Дополнительная информация</strong>

Просто идея или взломать.

div {
  background-color: blue;
  width: 10%;
  transition: background-color 0.5s, width 0.5s;
  font-size: 0;
}

div:hover {
  width: 20%;
  background-color: red;
}
  
img {
  width: 100%;
  height: auto;
  visibility: hidden;
}
<div>
  <!-- use an image with target aspect ratio. sample is a square -->
  <img src="http://i.imgur.com/9OPnZNk.png" />
</div>

В CSS есть новое свойство для этого: aspect-ratio.

https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio

Chrome и Edge полностью поддерживают это с V88, а Firefox поддерживает это с флагом с V81 (установлен layout.css.aspect-ratio.enabled к trueв about: config ).

Для получения информации о совместимости посетите https://caniuse.com/mdn-css_properties_aspect-ratio.

Новый тег соотношения сторон был бы великолепен, но он испортил расположение моих div. Традиционное решение заполнения div-обертки работает, но только регулирует размер в соответствии с шириной родительского элемента или области просмотра, что делает его проблематичным, когда высота является ограничивающим фактором.

Я нашел функция, чтобы быть очень полезной, и скорректировал традиционный метод следующим образом:

Скажем, что вы должны поддерживать ширину: 100px и высоту: 50px (то есть, 2:1). Просто сделайте следующее:

.pb-2to1 {
  padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}

We solved it like this:

      .square {
  width: 100%;
  max-height: 100%;
  aspect-ratio: 1;
  background: red;
  position: relative;
  margin: auto;
  top: 50%;
  transform: translateY(-50%);
}

see https://jsfiddle.net/r1jL3oqa/1/

Я только что создал div 2:1, размер которого изменился так, чтобы он занимал всю ширину, но затем уменьшил ширину, если это приведет к превышению верха или низа. Но учтите, что это будет работать только с размером окна, а не с размером родительского окна.

#scene {
    position: relative;
    top: 50vh;
    left: 50vw;
    width: 100vw;
    height: 50vw;
    max-height: 100vh;
    max-width: calc(100vh * 2);
    transform: translate(-50%, -50%);
}

Я уверен, что вы сможете найти правильные% для использования 4:3 вместо того 2:1.

Другие вопросы по тегам