根据宽度计算div的高度并保持比例[重复]

Posted

技术标签:

【中文标题】根据宽度计算div的高度并保持比例[重复]【英文标题】:Calculate height of div based off width & maintain proportion [duplicate] 【发布时间】: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 是不可能的,您可能可以将 calcheight: calc((1000px / 3) * .75) 之类的公式一起用于 footer 但是当您调整窗口大小时它无济于事,只有js 将能够在调整大小并将高度设置为3/4 的比例时捕获调整大小事件并计算每个像素 确实如此。没有 CSS 唯一的解决方案来解决这个问题。但是,如果您想编写更少的 JS,我相信您可以使用@Towkir 建议的公式来实现这一点,但您可以使用使用 JS 更新的 CSS 变量而不是 1000px @The24thDS 一个纯粹的CSS 解决方案是通过添加 5 行代码并为您提供所需的纵横比。 @Towkir 使用calc 不会使它成为纯粹的CSS 解决方案吗? @PeterDarmis 是的,calc 是一个纯 CSS 解决方案 【参考方案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: 500pxheight: 300pxpadding: 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。

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

【讨论】:

以上是关于根据宽度计算div的高度并保持比例[重复]的主要内容,如果未能解决你的问题,请参考以下文章

保持div的纵横比但在CSS中填充屏幕宽度和高度?

根据宽度和高度保持纵横比

根据宽度和高度保持纵横比

CSS:保持div的高度相对于其宽度[重复]

根据高度保持div的纵横比[重复]

js实现网页 高度和宽度成比例的代码