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

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

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

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

div keeping aspect ratio according to width of window

19 ответов


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

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

это приведет к <div> С высотой равной 75% из ширины своего контейнера (коэффициента сжатия 4:3).

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

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

Padding-нижние значения для других соотношений сторон и 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/100th ширины окна просмотра. [ 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 сетка квадратных divs

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


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

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

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

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

для этого я помещаю изображение перед встроенным объектом в класс" видео " div.

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

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

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

круто, да?

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


чтобы добавить к ответу 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-запрос.


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

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


Как говорится в здесь на 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


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

когда вы используете его, ваш 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. Сделайте положение контейнера / обертки относительным, поместите svg сначала как статически расположенное, а затем поместите абсолютно расположенное содержимое (вверху: 0; слева:0; справа:0; внизу:0;)

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

изображения.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%;" />

As @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, вы показываете use

.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.

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

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

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>

источник


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

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 */
}

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


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

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>

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

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

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

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


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

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

это улучшение по сравнению с принятым ответом:

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

.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>

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

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

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

Он выглядит отзывчивым, но он масштабируется. https://www.youtube.com/watch?v=xRcBMLI4jbg

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

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


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

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

<div style="width: 100%;">
   <div style="width: 50%; margin: 0 auto;">Content</div>
</div>

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

.squares{
  width: 30vw
  height: 30vw

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

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

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