【问题标题】:Calculate height of div based off width & maintain proportion [duplicate]根据宽度计算div的高度并保持比例[重复]
【发布时间】:2019-10-11 20:24:52
【问题描述】:

我正在寻找一个纯 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>

这是一支笔,展示了我拥有的东西。 https://codepen.io/nom3d/pen/arGpBV

这是一个显示调整大小时效果的 gif。请注意背景图像保持成比例,文本保持居中。

还想知道是否仅使用 CSS 是不可能的,如何使用 plain javascript 做到这一点,我需要将 id 添加到我的 div 中吗?

更新:这是一个简单的 javaScript 函数来处理这个任务

function setHeight(el,val){
    var box = document.querySelectorAll(el);
    var i;
    for(i = 0;i < box.length;i++){
        var width = box[i].offsetWidth;
        var height = width * val;
        box[i].style.height = height + 'px';        
    }
}
// set your element to target and the ratio value
setHeight('footer div',.75);
window.onresize = function(event) {
    setHeight('footer div',.75);
};

【问题讨论】:

  • 仅使用 css 是不可能的,您可能可以将 calc 与 height: calc((1000px / 3) * .75) 之类的公式一起用于 footer 但是当您调整窗口大小时它无济于事,只有js 将能够在调整大小并将高度设置为3/4 的比例时捕获调整大小事件并计算每个像素
  • 确实如此。没有 CSS 唯一的解决方案来解决这个问题。但是,如果您想编写更少的 JS,我相信您可以使用@Towkir 建议的公式来实现这一点,但您可以使用使用 JS 更新的 CSS 变量而不是 1000px。
  • @The24thDS 一个纯粹的CSS 解决方案是通过添加 5 行代码并为您提供所需的纵横比。
  • @Towkir 使用calc 不会使它成为纯粹的CSS 解决方案吗?
  • @PeterDarmis 是的,calc 是一个纯 CSS 解决方案

标签: javascript html css height responsive


【解决方案1】:

你试过了吗

footer div {
    height: 20vw;
}

还有 css 的 calc 属性可能会有所帮助

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

【讨论】:

  • 我相信如果这个浏览器高度改变,这将不会保持比例。此外,calc() 无法根据同一元素的宽度确定高度。
【解决方案2】:

你可以简单地考虑维护the aspect ratio using padding.的基本技巧

这是一个示例,我保留了两个示例,以便您进行比较,一个使用 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>

【讨论】:

  • 您介意在 FOOTER:not(.no-padd) DIV:before 行添加评论吗?我相信这将有助于理解答案。谢谢!
  • @drooh 这一行是一个简单的选择器,仅将逻辑应用于最后一个 fooer。我添加了两个页脚,一个带有 jquery(你的)和一个带有 CSS(我的)所以我只选择带有类 no-padd 的页脚来应用逻辑......我只是从我已经链接的问题中得到了答案[由于有赏金,我无法关闭重复项,因此我将其作为社区答案]
【解决方案3】:

在 CSS 中维护特定的高宽比通常是通过利用填充百分比总是计算based on the element's width这一事实来完成的。

例如,假设您有一个包含width: 500px、height: 300px 和padding: 10% 的元素。现在你可能会期望顶部和底部的填充是height 的 10%,左右填充是 width 的 10%。然而,这会产生不相等的垂直和水平填充,这与预期的相反 - 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>

【讨论】:

  • 使用 css flex 显示属性。检查此 URL 以获取更多详细信息。 developer.mozilla.org/en-US/docs/Web/CSS/flex
  • 根据我的经验,这是最简单、最适用的解决方案。顺便说一句,它也可以应用于视频以保持 HTML5 &lt;video&gt; 标签中内容的纵横比。
【解决方案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】:

    可能有点晚了,但也会添加我的解决方案。

    我认为我应该将其保留为通用解决方案,因此我决定不使用您的页脚类。但我相信你会成功的。

    在我看来,最简单的方法是使用填充计算来获得一个固定的比率和一些 div。

    1. 弹性容器
    2. Flex 项目(带有内边距):此容器用于保持分辨率。它的填充量取决于项目的宽度。 例如:项目宽度 = 100% --> 填充 = (100/4)*3 --> 75% 填充
    3. Flex-Item 内的内容容器,您可以在其中放置您的东西
    4. 内容容器内的背景-Div
    5. 把你需要的所有东西都作为同级元素放到 background-div 中

    这里有一个小玩意儿,一些 cmets 在代码中: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's 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's just to demonstrate that it's 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's 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's 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>
      

      您可以直接使用给定的代码,用于制作proposal宽度高度,您有2种不同的方式,下面给出其中一种,您可以使用百分比宽度和高度与计算相同,

      另一种方法是用 % 表示宽度,而不是高度,您可以用百分比给出 padding-bottom,所有这些都是相同的。

      【讨论】:

        【解决方案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);
        }
        &lt;img src="https://images.unsplash.com/photo-1559666126-84f389727b9a" /&gt;

        图片背景

        但是假设您希望容器管理大小而不考虑原始内容比例?只需使用背景图片。

        这个是 16:9(典型的宽屏)

        .fixedAspect {
          --aspectRatio: calc(9/16 * 100%);
          height: 0;
          padding-bottom: var(--aspectRatio);
          background-size: cover;
          background-position: center center;
        }
        &lt;div class="fixedAspect" style="background-image: url(https://images.unsplash.com/photo-1559662780-c3bab6f7e00b)"&gt;&lt;/div&gt;

        带有内容的 HTML 元素

        使用height:0 和一堆填充向元素添加内容可能不是最好的解决方案。但是我们可以通过使用伪类来解决这个问题。强制“最小高度”。

        奖励:如果您的内容大于您定义的 position: absolute; 包装器的纵横比,这不会中断。

        .fixedAspect {
          margin: 20px;
          background-color: #f6f3f0;
        }
        
        p {
          font-family: Helvetica, Arial, Sans-Serif;
          padding: 10px;
        }
        
        .fixedAspect:before {
          --aspectRatio: calc(5/20 * 100%);
          content: "";
          height:0;
          padding-top: var(--aspectRatio);
          
          /* so you can see the element */
          background-color: #F47E20;
          
          /* get this out of the way */
          float: left;
          width: 1px;
          margin-left:-1px;
        }
        
        .fixedAspect:after {
          /* we need to clear the float so its container respects height */
          content: "";
          display: table;
          clear: both;
        }
        <div class="fixedAspect">
          <p>My default size is a ratio of 20:5 but I'll grow if there's too much content.</p>
        </div>

        【讨论】:

          【解决方案8】:

          纯 CSS 修复

          相应地调整宽度和高度

          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>

          【讨论】:

            猜你喜欢
            • 2014-07-10
            • 2013-08-26
            • 2014-07-01
            • 2022-10-18
            • 2014-12-13
            • 2011-03-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多