【问题标题】:CSS: make div width proportional to heightCSS:使div宽度与高度成正比
【发布时间】:2014-05-05 13:32:29
【问题描述】:

这有点难以解释,但是:我想要一个响应高度的 div (height: 100%),它会按比例缩放 widthheight(不是反之亦然)。

我知道this method 使用padding-top hack 使高度与宽度成正比,但我需要它以相反的方式工作。话虽如此,我并不非常热衷于该方法中内容的绝对定位元素的额外要求,所以我意识到我很可能在这里要求月亮在棍子上。

为了帮助形象化,这里有一张图片:

...这里是jsFiddle,说明几乎相同的东西。

值得注意的是,我已经在使用:before:after 伪元素来垂直对齐要按比例缩放的框的内容。

我真的,真的很喜欢不必恢复到 jQuery,只是因为对调整大小处理程序和通常更多的调试有内在的要求......但如果这是我唯一的选择,那么 fiat。

【问题讨论】:

  • 恐怕你必须使用 javascript...
  • 除了使用 paddingmargin jsfiddle.net/V2dyZ/3 的技巧之外别无他法。不知何故,我们必须找到宽度和高度之间的某种关系,以便我们可以相应地设置高度,但是通常width 仅相对于父级的widthheight 仅相对于父级的@987654335 @,marginpadding 只有 1 个特别之处,即它们的 百分比(相对值)值基于父级的 width,无论您设置 padding-top,@ 987654340@ or margin-top, margin-bottom,所以我们有一个解决方案(只有?)

标签: html css scale


【解决方案1】:

哦,您可能可以使用“填充顶部”技巧。

width: 50%;
height: 0;
padding-bottom: 50%;

http://absolide.tumblr.com/post/7317210512/full-css-fluid-squares

或者:

.square-box{
    position: relative;
    width: 50%;
    overflow: hidden;
    background: #4679BD;
}
.square-box:before{
    content: "";
    display: block;
    padding-top: 100%;
}

http://codeitdown.com/css-square-rectangle/

CSS 中的垂直填充与元素的宽度有关,而不是高度。

【讨论】:

  • 第一个不太适用,因为div可能包含一些内容,除非我们用绝对定位稍微调整一下……当然如果我们只需要一个空的方形div就可以了.
  • 是的,我知道那个;不幸的是,这种设计的规范是宽度必须与高度成比例地设置,而不是相反。看起来我很可能会为此转向 jQuery。
【解决方案2】:

一段时间以来,我一直在想有一个纯 CSS 解决方案来解决这个问题。我终于想出了一个使用 ems 的解决方案,可以使用 vws 逐步增强:

完整的工作演示和解释见 codepen 链接:

http://codepen.io/patrickkunka/pen/yxugb

简化版:

.parent {
  font-size: 250px; // height of container
  height: 1em;
}

.child {
  height: 100%;
  width: 1em; // 100% of height
}

【讨论】:

  • 在这里使用font-size 看起来真的很丑陋并且可能不方便。
  • 超迟收!我完全忘记了我问过这个问题,然后我在谷歌上搜索完全相同的东西,我的问题是第一个。事实证明,这正是我所追求的(对内联比例进行了一点调整——根据图像大小比计算)。感谢您的提示!
  • 我们不能有固定高度的情况怎么办... :(
  • 您需要知道高度。它不需要以 px 为单位设置,但是您可以使用任何大小单位(remvhvw 等)。如果高度根据视口大小而变化,您还可以通过断点更改 height 值。
【解决方案3】:

字体解决方案要求知道高度。我找到了一种解决方案,可以在宽度和高度未知的父 div 内使元素成比例。 Here is a demo.

我使用的技巧是将图像用作分隔符。代码解释:

<div class="heightLimit">
 <img width="2048" height="2048" class="spacer"
  src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAA
       P///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
 <div class="filler">
  <div class="proportional">
  </div>
 </div>
</div>

所以它不是最漂亮的,有两个额外的 div 和一个无用的图像。但情况可能更糟。图像元素需要具有所需尺寸的宽度和高度。宽度和高度需要与允许的最大尺寸一样大(一个功能!)。

CSS:

.heightLimit {
 position: absolute;
 top: 0;
 left: 0;
 height: 100%;
 width: auto;
 max-width: 100%;
 overflow: hidden;
}

这个元素是为了限制高度,但是水平扩展(width: auto)虽然永远不会超出父级(max-width)。溢出需要隐藏,因为有些子元素会突出到 div 之外。

.spacer {
 width: auto;
 max-height: 100%;
 visibility: hidden;
}

此图像是不可见的,并且与高度成比例缩放,而宽度会调整并强制调整父级的宽度。

.filler {
 position: absolute;
 top: 0;
 left: 0;
 bottom: 0;
 right: 0;
}

需要此元素以使用绝对定位的容器填充空间。

.proportional {
 position: relative;
 width: 100%;
 height: 0;
 padding-bottom: 100%;
}

在这里,我们的比例元素使用熟悉的 padding-bottom 技巧获得与宽度成比例的高度。

不幸的是,Chrome 和 IE 中存在一个错误,因此如果您使用 Javascript 修改父元素,例如在我的演示中,尺寸将不会更新。如我的演示所示,有一个 hack 可以用来解决这个问题。

【讨论】:

  • data:image/gif;base64,R0lGODlhAQABAIAAAAAAA P///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7的意义是什么?可以改用常规网址吗?具体来说,我不明白所有看起来毫无意义的随机字符的用途。
【解决方案4】:

您可以使用视图高度 (vh) 作为 宽度 的单位。

这是您要求的 20 像素边距的示例。

 .parent {
   margin : 20px;
}
.child {
   width: calc(100vh - 40px);
   height : calc(100vh - 40px);
   margin:0 auto;
   background: red;
   box-sizing:border-box;
   padding:10px;
}

看小提琴: https://jsfiddle.net/svobczp4/

【讨论】:

    【解决方案5】:

    根据@kunkalabs 的回答(这真的很聪明),我想出了一个解决方案,可以让您保留继承的字体大小。

    HTML:

    <div id='rect'>
        <div id='content'>Text</div>
    </div>
    

    CSS:

    #rect {
        font-size: 1000%;
        height: 1em;
        width: 1em;
        position: relative;
    }
    
    #content {
        font-size: 10%;
    }
    

    所以基本上#content 的字体大小是 (100 / $rectFontSize) * 矩形的 100%。如果您需要矩形的确定像素大小,您可以设置#rect 的父级字体大小……否则只需调整字体大小,直到它达到您想要的位置(并在此过程中激怒您的设计师) .

    【讨论】:

    • 有没有办法让这个比例响应视口宽度?
    • 好问题,肯定有(尽管您失去了继承的字体宽度),只需更改“#rect font-width 以使用视口相对 CSS 单位作为字体大小。所以像 @ 987654325@ 表示在上述情况下,您的矩形将始终是视口宽度和高度的 10%。如果您希望内容的字体缩放到(这不是一个坏主意),请将其保留为百分比,否则您将拥有设置像素值。
    • 您的意思是“更改#rect 的字体-大小”,否则,谢谢。
    【解决方案6】:

    您可以通过使用 SVG 来实现。

    视情况而定,但在某些情况下它确实很有用。举个例子——你可以设置background-image而不设置固定高度,或者使用它来嵌入&lt;iframe&gt;,比例为16:9position:absolute

    对于3:2比率设置viewBox="0 0 3 2"等等。

    例子:

    div{width:35%;background-color:red}
    svg{width:100%;display:block;visibility:hidden}
    <div>
      <svg viewBox="0 0 3 2"></svg>
    </div>

    【讨论】:

      【解决方案7】:

      在较新的浏览器上,我们可以使用固定高度的aspect-ratio,宽度会相应计算。

      img {
          aspect-ratio: 1.2;
          height: 250px;
          max-width: 500px;
      }
      

      但是浏览器对aspect-ratio 的支持还不够好。我喜欢@Jakub Muda 提出的SVG 解决方案,除了它需要修改标记。我通过使用content 属性将SVG 移动到CSS。在较新的浏览器上,它会禁用 SVG hack 并切换到 aspect-ratio 属性。

      document.querySelector('.nav').addEventListener('click', function(e) {
        var index = parseInt(e.target.dataset.index);
        if (!index) {
          return;
        }
      
        var elements = document.querySelectorAll('.box');
        for (var i = elements.length; i > 0; i--) {
          elements[i - 1].classList.toggle('hide', i !== index);
        }
      
      });
      .wrapper {
        max-width: 500px;
        margin: 0 auto;
        width: 100%;
        height: 250px;
        text-align: center;
        background: green;
      }
      
      .box {
        display: inline-flex;
        position: relative;
        max-width: 100%;
      }
      
      
      /* SVG Hack */
      
      .box::before {
        display: block;
        line-height: 0;
        max-width: 100%;
        content: 'test';
      }
      
      [data-aspect-ratio="1"]::before {
        content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1' height='250'></svg>");
      }
      
      [data-aspect-ratio="2"]::before {
        content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 1' height='250'></svg>");
      }
      
      [data-aspect-ratio="3"]::before {
        content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 1' height='250'></svg>");
      }
      
      @supports (aspect-ratio1: 1) {
        /* Modern browsers */
        .box {
          height: 100%;
          background: green;
        }
        .box::before {
          display: none;
        }
        [data-aspect-ratio="1"] {
          aspect-ratio: 1;
        }
        [data-aspect-ratio="2"] {
          aspect-ratio: 2;
        }
        [data-aspect-ratio="3"] {
          aspect-ratio: 2;
        }
      }
      
      .content {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
      }
      
      .content>svg {
        display: block;
        width: 100%;
        position: absolute;
        top: 50%;
        left: 50%;
        height: auto;
        transform: translate(-50%, -50%);
      }
      
      .nav {
        text-align: center;
      }
      
      .hide {
        display: none;
      }
      <!doctype html>
      <html lang="en">
      
      <head>
        <title>Width proportional to height in CSS</title>
      </head>
      
      <body>
        <div class="wrapper">
          <div class="box" data-aspect-ratio="1">
            <div class="content">
              <svg viewBox="0 0 100 100" width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="96" height="96" style="fill:#DEDEDE;stroke:#555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="#555555">100&#215;100</text></svg>
            </div>
          </div>
          <div class="box hide" data-aspect-ratio="2">
            <div class="content">
              <svg viewBox="0 0 200 100" width="200" height="100" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="196" height="96" style="fill:#DEDEDE;stroke:#555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="#555555">200&#215;100</text></svg>
            </div>
          </div>
          <div class="box hide" data-aspect-ratio="3">
            <div class="content">
              <svg viewBox="0 0 300 100" width="300" height="100" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="296" height="96" style="fill:#DEDEDE;stroke:#555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="#555555">300&#215;100</text></svg>
            </div>
          </div>
        </div>
      
        <div class="nav">
          <button data-index="1">1</button>
          <button data-index="2">2</button>
          <button data-index="3">3</button>
        </div>
      </body>
      
      </html>

      【讨论】:

        【解决方案8】:

        使父 DIV 表现得像一个表格单元格并垂直对齐子元素。不需要做任何填充技巧。

        HTML

        <div class="parent">
        <img src="foo.jpg" />
        </div>
        

        CSS

        .parent { width:300px; height:300px; display:table-cell; vertical-align:middle; }
        

        【讨论】:

        • 垂直居中的内容不是问题 - 它使包含元素的高度与其宽度成比例地响应。在您的示例中,您对两者都使用硬编码值。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多