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

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

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

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

div keeping aspect ratio according to width of window

Ответы

Ответ 1

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

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

Ответ 2

vw единиц:

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

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

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

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

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

Ответ 3

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

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

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

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

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

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

Вероятно, вы уже должны иметь минимальную ширину, как это определено для жидких элементов вашего веб-сайта. Если нет, рекомендуется сделать это, чтобы избежать измельчения элементов или перекрытия, когда окно браузера становится слишком маленьким. В какой-то момент лучше иметь полосу прокрутки. Наименьшая по ширине веб-страница должна быть где-то около ~ 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% элемента видеокласса корректироваться с помощью изображения.

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

Как указано здесь на 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

Ответ 7

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

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

Ответ 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>

Обратите внимание, что inline 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%;" />

Ответ 9

Поскольку @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 75.Если вы хотите сначала обеспечить высоту, вы должны переключить ширину и высоту, например, height:100vh;width: calc(100vh * 9/16) для портрета 9:16.

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

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

Ответ 10

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

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

Ответ 11

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>

источник

Ответ 12

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

html выглядит следующим образом:

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

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

ratio = > от 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 */
}

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

Ответ 13

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

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>

Ответ 14

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

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

Ответ 15

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

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

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

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

Ответ 16

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

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

Ответ 17

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

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

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

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

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

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

Ответ 18

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

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

Ответ 19

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

Элемент 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>:

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

Ответ 20

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

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

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

Ответ 21

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

.squares{
  width: 30vw
  height: 30vw

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

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

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