Рассчитать высоту div на основе ширины и сохранить пропорции

Я ищу чистое решение CSS для того, что я здесь сделал, используя jQuery, чтобы помочь.

В основном у меня есть 3 div, которые равномерно распределены по ширине в контейнере. Они поддерживают соотношение 3/4 с высотой, вычисляемой по ширине. Кроме того, у каждого div есть фоновое изображение, которое остается пропорциональным, и некоторый текст, который центрируется по горизонтали и вертикали.

$(document).ready(function() {
  function setw() {
    var footdivwidth = $('footer div').width();
    var footdivheight = footdivwidth * .75;
    $('footer div').css({
      'height': footdivheight + 'px'
    });
    $('footer div span').html('w: ' + footdivwidth + '<br>h: ' + footdivheight);
  }
  setw();
  $(window).resize(function() {
    setw();
  })
});
FOOTER {
  max-width: 1000px;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

FOOTER DIV {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  flex: 1;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}

FOOTER DIV SPAN {
  display: inline-block;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<footer>
  <div><span>left photo</span></div>
  <div><span>center photo</span></div>
  <div><span>right photo and more text</span></div>
</footer>

Ответ 1

Поддержание определенного соотношения высоты: ширины в CSS обычно выполняется с использованием того факта, что процент заполнения всегда вычисляется на основе ширины элемента.

Например, предположим, что у вас есть элемент с width: 500px, height: 300px и height: 300px padding: 10%. Теперь вы можете ожидать, что верхний и нижний отступы будут на 10% height, а левый и правый отступы - на 10% width. Однако это дало бы неравные вертикальные и горизонтальные отступы, что противоречит тому, что предполагается - равные отступы в 10%. Чтобы понять это, нам нужно основать процент заполнения на измерении сохранения, и этот размер был выбран в качестве ширины.

Таким образом, чтобы всегда иметь элемент с отношением высоты: ширины 3: 4, мы можем установить высоту равной 0, а нижний (или верхний) отступ - 3/4 ширины.

В вашем примере Flex получает ширину 33%. При соотношении 3: 4 нижнее заполнение должно составлять 33% * 3/4 или 24,74%. Ваш CSS может выглядеть так:

width: 33%;
height: 0;
padding-bottom: 24.75%;

Обратите внимание, что, поскольку высота равна 0, элемент должен быть относительно позиционирован с абсолютно позиционированной оберткой внутри. Если вы попытаетесь поместить контент прямо в div, это нарушит соотношение. Ваш код выше может быть изменен таким образом:

footer {
  max-width: 1000px;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
footer div {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  position: relative;
  width: 33%;
  height: 0;
  padding-bottom: 24.75%;
}
footer div span {
  /* Used as content wrapper, with flex to centre content */
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}
<footer>
  <div><span>left photo</span></div>
  <div><span>center photo</span></div>
  <div><span>right photo and more text</span></div>
</footer>

Ответ 3

Вы можете просто рассмотреть основной прием для сохранения соотношения сторон с помощью отступов .

Вот пример, где я сохранил оба примера, чтобы вы могли сравнить, один с использованием jQuery, а другой с использованием чистого CSS.

$(document).ready(function() {
  function setw() {
    var footdivwidth = $('footer div').width();
    var footdivheight = footdivwidth * .75;
    $('footer.no-padd div').css({
      'height': footdivheight + 'px'
    });
    $('footer div span').html('w: ' + footdivwidth + '<br>h: ' + footdivheight);
  }
  setw();
  $(window).resize(function() {
    setw();
  })
});
FOOTER {
  max-width: 1000px;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

FOOTER DIV {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  flex: 1;
  text-align: center;
  display: flex
}
FOOTER:not(.no-padd) DIV:before {
  content:"";
  padding-top: 75%;
}

FOOTER DIV SPAN {
  margin:auto;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<footer class="no-padd">
  <div><span>left photo</span></div>
  <div><span>center photo</span></div>
  <div><span>right photo and more text</span></div>
</footer>

<footer >
  <div><span>left photo</span></div>
  <div><span>center photo</span></div>
  <div><span>right photo and more text</span></div>
</footer>

Ответ 4

Быстрое чистое CSS решение потребует добавления в FOOTER DIV

  max-width: 333px;
  width: calc(100vw/3);
  height: calc(100vw*0.75/3);
  max-height: calc(333px*0.75);

и добавить в FOOTER

  width: 100vw;

// Javascript is only used in order to check the width/height ratio in console live.
$(document).ready(function() {

  $(window).resize(function() {
    console.log('width: ' + $('footer div').width() + ', height: ' + $('footer div').height());
  });
  
});
FOOTER {
  max-width: 1000px;
  width: 100vw;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  /*justify-content: space-between;*/
}

FOOTER DIV {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  flex: 1;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 333px;
  width: calc(100vw/3);
  height: calc(100vw*0.75/3);
  max-height: calc(333px*0.75);
}

FOOTER DIV SPAN {
  display: inline-block;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<footer>
  <div><span>left photo</span></div>
  <div><span>center photo</span></div>
  <div><span>right photo and more text</span></div>
</footer>

Ответ 5

Возможно, немного поздно, но добавлю и мое решение.

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

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

  1. Контейнер Flex
  2. Элементы Flex (с отступом на нем): этот контейнер используется для поддержания разрешения. Количество отступов для него зависит от ширины предмета. Например: ширина элемента = 100% → заполнение = (100/4) * 3 → 75% заполнения
  3. Контейнер для содержимого внутри Flex-Item, куда вы можете положить свои вещи
  4. Background-Div внутри контейнера содержимого
  5. Положите все, что вам нужно, как брат в фоновом режиме

Здесь можно поиграться, некоторые комментарии в коде: https://jsfiddle.net/Hoargarth/Lry5gbsq/Не стесняйтесь спрашивать, если вам что-то нужно

Просто краткое замечание по всем этим контейнерам: вы можете сделать это только с помощью flex-item и еще одного контейнера. Но, на мой взгляд, с дополнительным контейнером он становится более гибким, если вам нужны какие-либо события при наведении курсора, анимация или другие экзотические вещи. Для простого решения см. Эту скрипку: https://jsfiddle.net/Hoargarth/m57b9jcw/

.container {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
}

/* padding bottom gives the height of the container, 33.33% padding would be a quadratic box. 100% would be the same height as the container width. Therefore simple trignomometry, (100/4) * 3 = 75%; or for screen width > 500px: (33.33 / 4) * 3 for a 4/3 resolution. You'll find the media query at the end of the css. It just to demonstrate that it working with media queries as well. */
.item {
  position: relative;
  width: 100%;
  padding-bottom: 75%;
}

/* Overflow hidden so nothing can overlap to the other items */
.content-wrapper {
  position: absolute;
  overflow: hidden;
  width: 100%;
  height: 100%;
}

.image-holder {
  position: relative;
  height: 100%;
  background-image: url("https://previews.123rf.com/images/happydancing/happydancing1706/happydancing170600014/80282512-flat-lay-photo-of-workspace-desk-with-laptop-smartphone-blank-notebook-and-green-plant-with-copy-spa.jpg");
  background-size: cover;
  background-position: 50%;
  background-repeat: no-repeat;
}

/* Absolute positioned by 50% top, left; To completely center it, you have to translate the holder back by it own half width and height transform: translate(-50%, -50%) */
.text-holder {
  position: absolute;
  top: 50%;
  left: 50%;
  padding: 10px;
  width: 70%;
  background-color: rgba(255, 255, 255, 0.5);
  transform: translate(-50%, -50%);
  text-align: center;
}

/* Simple media Query to test it. Be aware: If the item width is changing, the padding has to change as well */
@media (min-width: 500px) {
  .item {
    width: 33.33%;
    padding-bottom: 24.75%;
  }
}
<div class="container">

  <div class="item">
    <div class="content-wrapper">
      <div class="image-holder"></div>
      <div class="text-holder">
        <p>
          Some Centered Text
        </p>
      </div>
    </div>
  </div>
  
  <div class="item">
    <div class="content-wrapper">
      <div class="image-holder"></div>
      <div class="text-holder">
        <p>
          Some Centered Text but larger and longer so we see a difference
        </p>
      </div>
    </div>
  </div>
  
  <div class="item">
    <div class="content-wrapper">
      <div class="image-holder"></div>
      <div class="text-holder">
        <p>
          Groot
        </p>
      </div>
    </div>
  </div>
  
</div>

Ответ 6

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        FOOTER {
            max-width: 1000px;
            margin: 0 auto;
            background-color: rgba(0, 0, 0, 0.171);
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
        }
        FOOTER DIV {
            position: relative;
            width: calc(100vw / 3);
            height: calc(100vw / 3 * 0.75 );
            max-height: calc(1000px / 3 * 0.75 );
            background-image: url('https://learnwebdesign.online/img/bg.jpg');
            background-position: center;
            background-size: cover;
            background-repeat: no-repeat;
            flex: 1;
            text-align: center;
            display: flex;
            align-items: center;
            justify-content: center;

        }
        FOOTER DIV SPAN {
            position: absolute;
            top:50%;
            left: 50%;
            transform: translate(-50%, -50%);
            display: inline-block;
            text-align: center;
            background-color: rgba(165, 165, 165, 0.282);
            padding: 7px 15px;
            border-radius: 3px;
            color: #FFFFFF;
            text-transform: uppercase;
            font-weight: bold;
            letter-spacing: 2px;
            font-size: 21px;
        }
    </style>
</head>
<body>
    <footer>
        <div><span>left photo</span></div>
        <div><span>center photo</span></div>
        <div><span>right photo and more text</span></div>
    </footer>
</body>
</html>

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

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

Ответ 7

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

Основная идея заключается в том, что padding в процентах рассчитывается на основе ширины элемента. Это означает, что padding-bottom: 100% == element.width (в данном случае квадрат). Мы можем использовать этот трюк, вычислив соотношение и используя его для заполнения.


Пример изображения

Изображения немного странные в том, что они уже имеют соотношение сторон, так что вы можете просто установить height: auto и быть готовым к работе.

Соотношение: 4: 3

img {
  --aspectRatio: calc(3/4 * 100%);
  display:block;
  width: 300px; // this one needs a width to work.
  height:var(--aspectRatio);
}
<img src="https://images.unsplash.com/photo-1559666126-84f389727b9a" />

Ответ 8

PURE CSS FIX

Отрегулируйте ширину и высоту соответственно

footer {
    display: flex;
    width: 100vw;
    align-items: center;
    justify-content: center;
}

.responsive-box {
    width: 33vw;
    border: 1px solid blue;
    max-width: 333px;
    min-width: 35px;
    flex-flow: row;
    height: 60vh;
  position: relative;
}

.responsive-box span {
   position: absolute;
   top:40%;
   bottom:0;
   left:0;
   right:0;
   text-align: center;
}
<footer>
  <div class="responsive-box left"><span>left photo</span></div>
  <div class="responsive-box center"><span>center photo</span></div>
  <div class="responsive-box right"><span>right photo and more text</span></div>
</footer>