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

1059

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

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

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

div сохраняя пропорции в соответствии с шириной окна

jackb
источник
3
Я писал о различных подходах к этому в моей статье CSS-хитрости о масштабировании
Зак
2
Я пришел к этому Q & A очень поздно, но я должен прокомментировать. Хотя это очень дисциплинировано и в рамках правил SO каждого, кто отвечает, стараются изо всех сил, чтобы удовлетворить требование «только CSS» вопроса, довольно удивительно, что, за исключением ответа user007, расположенного внизу страницы, нет. один упомянул очевидное: не существует надежного решения только для CSS, эта проблема требует Javascript. Новичок, зашедший на эту страницу, может потратить драгоценное время на переключение с одного набора плюсов / минусов на другой, прежде чем погаснет лампочка: только CSS не подойдет.
Тео д'Ор
1
Я написал небольшой инструмент, который облегчает предварительный просмотр и вычисление соотношений сторон, aspectrat.io . Он также генерирует соответствующий код CSS / Sass / Less, который вы можете скопировать и вставить в свои проекты. Надеюсь, люди найдут это полезным.
Райан Хефнер
см. этот пример: w3schools.com/howto/howto_css_aspect_ratio.asp ..... это сработало
Кристиан Агудело
1
Этот вопрос для установки высоты на основе ширины . Если вам нужно обратное, проверьте настройку ширины элемента на основе высоты с помощью CSS .
Джон Меллор

Ответы:

1354

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

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

/* demonstration purposed only : non-essential */
.demoWrapper {
  padding: 10px;
  background: white;
  box-sizing: border-box;
  resize: horizontal;
  border: 1px dashed;
  overflow: auto;
  max-width: 100%;
  height: calc(100vh - 16px);
}
<div class="demoWrapper">
  <div></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;
}

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

Веб-дизайнер
источник
29
@schellmax, это потому, что padding% вычисляется относительно ширины текущего элемента, а высота как% вычисляется относительно высоты родительского элемента. Кроме того, абсолютные позиции рассчитываются относительно внешнего контейнера элемента, который включает в себя область заполнения. Для получения дополнительной информации Google "CSS Box Model"
Ансон Као
11
Это, кажется, не работает вложенным способом. Он работает на первом уровне, но при попытке сделать то же самое внутри соотношения сторон, поддерживающего div, процент заполнения снизу, кажется, применяется к ширине родительского элемента. Вот пример, где .stretchy-wrap.onethird padding-bottom 25% на самом деле составляет 25% от родительской ширины. Может кто-нибудь объяснить это?
Misterparker
4
Просто восхитительно. Меня убивает, что эта техника не сработает, если вы хотите зафиксировать высоту на 100%. @Misterparker, метод основан на расчетах ширины и отступов, выполняемых для одной и той же ссылки; вы не можете использовать ширину меньше 100%, как в вашем примере.
Стевелушер
2
@Misterparker Да, процентное заполнение рассчитывается пропорционально ширине родительского элемента. Посмотрите более подробный пример, который я разместил в редактировании моего ответа. Моя обновленная демонстрация демонстрирует «вложенную моду», о которой вы говорили.
Web_Designer
3
того факта, что он продемонстрировал, что это работает, достаточно, чтобы убедить меня, что это лучший ответ, который я когда-либо видел на SO. кричите моему человеку @Web_Designer
410

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 для получения дополнительной информации

веб-Тики
источник
14
Это должен быть принятый ответ. Возможно, не сейчас, но в будущем. Блоки vw теперь поддерживаются в большинстве браузеров .
Авг
3
@vivekmaharajh оба метода хороши, у каждого есть свои плюсы и минусы. Использование одного или другого в значительной степени зависит от ситуации.
web-tiki
11
@ web-tiki, ты прав. Я столкнулся с одной проблемой - она ​​предполагает, что ширина элемента пропорциональна ширине области просмотра, что не будет иметь место, если 1) у вас есть такие вещи, как желоба с фиксированной шириной, или 2) у вас установлен max-width для некоторых из ваших элементов.
Вивек Махарадж
1
Может быть, это просто Chrome v47beta, но когда я установил div width:50%и height:50vwвысота немного выше ширины, так что не совсем пропорция 1: 1. Любые идеи?
thdoan
2
@ 10basetom это нормальное поведение. Блоки vw содержат ширину полосы прокрутки, а% width - нет. Разница между высотой и шириной будет зависеть от размера полосы прокрутки, которая зависит от браузера.
web-tiki
26

Я нашел способ сделать это с помощью 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% элемента класса видео, настраиваемого изображением.

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

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

Forgo
источник
17

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

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, которая может не работать с вашими целевыми браузерами. Вы можете проверить совместимость (например, на caniuse.com ).

Флориан Брейш
источник
14

Чтобы добавить к ответу 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.

nabrown
источник
Отличное решение. В моем случае я знаю «естественный» размер изображения при размещении его в DOM, и мне нужно иметь заполнитель изображения с надлежащей высотой, чтобы предотвратить дальнейшую прокрутку после загрузки изображений браузером. В .ar-outer у меня есть ширина изображения в пикселях, в .ar у меня есть padding-bottom, рассчитанный из реального соотношения сторон изображения. Вместо ar-inner у меня есть само изображение (<img>). Однако мне пришлось установить ширину на 100% вместо установки сверху, снизу, слева и справа. Когда я устанавливаю maxWidth на ar-outer, изображение хорошо масштабируется, когда родительский объект маленький, но не масштабируется до большего размера, чем его естественный размер.
Ми-Ла
13

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

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

Ergo, правильный пример адаптивного 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

Марк А
источник
13

Поскольку @ 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чтобы изменить соотношение.
Wener
источник
11

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

  • Использует псевдоэлементы вместо 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>

Салман А
источник
как отключить вертикальное растяжение коробки? strictily говоря растяжку DIV не поддерживает его соотношение сторон
Флориан
Если содержимое выше ожидаемой высоты, прямоугольник будет растягиваться вертикально. Эта идея лучше всего используется с контентом, который может растягиваться, чтобы соответствовать его родительским измерениям, например, видео и изображениям.
Салман
10

Я наткнулся на умное решение, используя <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>

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


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

дао
источник
9

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

Когда вы используете его, ваш 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в высоту / ширину и все.

pie6k
источник
3
Вы должны использовать data-keep-ratioне keep-ratioи получить его значение с помощью$(this).data('keep-ratio');
Роберт
ваш код работает сейчас и, возможно, будет работать вечно, но он не является стандартным, и браузеры могут перестать поддерживать его в любое время в будущем
Robert
1
Использование JS здесь вызовет плохие новости!
Амир Хоссейн Ахмади
8

Вы можете использовать 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%;" />
Мацей Кравчик
источник
7

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>

источник

Горди
источник
15
Просто FYI ... Вы можете сделать это точно (используя селекторы атрибутов) в точно такое же количество строк, используя простой CSS. [data-aspect-ratio]Селектор атрибута доступен для вас в CSS.
Рневиус
6

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

Я попытался соединить их вместе, чтобы создать полностью переносимое и масштабируемое решение ... Хитрость заключается в том, чтобы использовать автоматическое масштабирование изображения, но использовать встроенный элемент 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.

Salketer
источник
4

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

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>

orlland
источник
Это решение не только для CSS ... Теперь, если бы вы использовали изображение в кодировке base64 в псевдоэлементе, это было бы классным решением.
Ренвиус
1
Там действительно нет решения только для CSS. HTML является основным компонентом сети. Я считаю, что цель вопроса - воздержаться от использования JS, возможно, для экономии ресурсов / обработки.
orlland
Я не уверен, будет ли работать псевдоэлемент. Я использовал свойство элемента img, чтобы сохранить соотношение сторон для этого решения.
Орлланд,
Хорошо, но он вычисляет высоту только при изменении ширины. Это должно происходить в обе стороны, поэтому, когда я уменьшаю высоту, ширина также пересчитывается. В противном случае это бесполезно ..
Ωmega
4

Допустим, у вас есть 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 */
}

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

Ахмед Ид
источник
4

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

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

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

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

user007
источник
1
Хотя я не видел и не пробовал ваш код (у меня уже есть свой), я проголосовал за ваш ответ только за то, что вы представляете единственное надежное решение, скрипт JS.
Тео д'Ор
Вопрос специально задал вопрос о решении, которое не нуждается в Javascript.
Flimm
4

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

@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
} 
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
} 
Moonlite
источник
4

Я хотел бы поделиться своим решением, где у меня есть 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>

LaVomit
источник
3

Вы можете достичь этого с помощью 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>

Якуб Муда
источник
3

Простой способ сохранить соотношение сторон, используя элемент canvas.

Попробуйте изменить размер 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>

Gbr22
источник
да, помогло мне, теперь я могу использовать его для настройки высоты родительского div изображения)
Алекс
2

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

.pb-2to1 {
  padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}
Сайед
источник
1

Вы можете использовать макет потока (FWD).

https://en.wikipedia.org/wiki/Adaptive_web_design

Он будет масштабировать и поддерживать макет, он немного сложен, но позволяет изменять размер страницы, не выдвигая содержимое, например (RWD).

Это похоже на отзывчивость, но это масштабирование. https://www.youtube.com/watch?v=xRcBMLI4jbg

Вы можете найти формулу масштабирования CSS здесь:

http://plugnedit.com/pnew/928-2/

user1410288
источник
Как это отвечает на вопрос?
Flimm
0

Я использовал новое решение.

.squares{
  width: 30vw
  height: 30vw

К основному соотношению сторон

.aspect-ratio
  width: 10vw
  height: 10vh

Однако это относится ко всему окну просмотра. Итак, если вам нужен div, который составляет 30% ширины области просмотра, вы можете использовать 30vw вместо этого, и, поскольку вы знаете ширину, вы повторно используете их по высоте, используя calc и vw unit.

Эшварен Манохарен
источник
7
Разве это не то, что уже было указано на втором месте в рейтинге?
Рневиус
-4

Если бы вся структура контейнера была основана на процентах, это было бы поведением по умолчанию, можете ли вы привести более конкретный пример?

Ниже приведен пример того, что я имею в виду, если бы вся ваша родительская иерархия была основана на%, любая настройка окна браузера работала бы без каких-либо дополнительных js / css, разве это не возможно с вашим макетом?

<div style="width: 100%;">
   <div style="width: 50%; margin: 0 auto;">Content</div>
</div>
Ник Крейвер
источник
1
Смотрите мое редактирование на оригинальный вопрос. Я не вижу, где эта техника сохранит соотношение сторон, высота не изменится.
Джекб