首页 文章

使用CSS保持div的宽高比

提问于
浏览
864

我想创建一个 div ,可以随着窗口宽度的变化改变其宽度/高度 .

是否有任何CSS3规则允许高度根据宽度变化 while maintaining its aspect ratio

我知道我可以通过JavaScript实现这一点,但我更喜欢只使用CSS .

div keeping aspect ratio according to width of window

21 回答

  • 11

    只需为 padding-bottom 创建一个包含 <div> 的百分比值,如下所示:

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

    它将导致 <div> 的高度等于其容器宽度的75%(纵横比为4:3) .

    这取决于填充的事实:

    百分比是根据生成的框的包含块[...]的宽度计算的(来源:w3.org,强调我的)

    其他宽高比和100%宽度的填充底部值:

    aspect ratio  | padding-bottom value
    --------------|----------------------
        16:9      |       56.25%
        4:3       |       75%
        3:2       |       66.66%
        8:5       |       62.5%
    

    Placing content in the div :

    为了保持div的纵横比并防止其内容被拉伸,您需要添加一个绝对定位的子项并将其拉伸到包装器的边缘,并使用:

    div.stretchy-wrapper {
      position: relative;
    }
    
    div.stretchy-wrapper > div {
      position: absolute;
      top: 0; bottom: 0; left: 0; right: 0;
    }
    

    Here's a demo和另一个更深入demo

  • 1

    大众单位:

    您可以将 vw 单位用于元素的 width and height . 这允许基于视口宽度保留元素的宽高比 .

    vw:视口宽度的1/100 . [MDN]

    或者,您也可以使用 vh 作为视口高度,甚至使用 vmin / vmax 来使用视口尺寸的较小/较大(讨论here) .

    示例:1:1宽高比

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

    对于其他宽高比,您可以使用下表根据元素的宽度计算高度值:

    aspect ratio  |  multiply width by
    -----------------------------------
         1:1      |         1
         1:3      |         3
         4:3      |        0.75
        16:9      |       0.5625
    

    示例:方形div的4x4网格

    body {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
    }
    div {
      width: 23vw;
      height: 23vw;
      margin: 0.5vw auto;
      background: gold;
    }
    
    <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
    

    这是Fiddle with this demo,这是一个制作responsive grid of squares with verticaly and horizontaly centered content的解决方案 .


    浏览器对vh / vw单元的支持是IE9见canIuse for more info

  • 0

    我已经找到了使用CSS执行此操作的方法,但您必须小心,因为它可能会根据您自己的网站流量而改变 . 我这样做是为了在我的网站的流体宽度部分内嵌入具有恒定宽高比的视频 .

    假设您有这样的嵌入式视频:

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

    然后,您可以将所有内容放在带有“视频”类的div中 . 此视频类可能是您网站中的流动元素,因此它本身没有直接的高度限制,但是当您调整浏览器大小时,它将根据网站的流量改变宽度 . 这将是您可能尝试在保持视频的某个宽高比的同时获取嵌入视频的元素 .

    为了做到这一点,我在“视频”类div中的嵌入对象之前放置了一个图像 .

    !重要的是,图像具有您希望保持的正确宽高比 . 此外,请确保图像的大小至少与您期望的视频(或者您维护A.R.的任何内容)一样大,以便根据您的布局获得 . 这将避免在调整百分比时图像分辨率中的任何潜在问题 . 例如,如果您想保持3:2的宽高比,请不要只使用3px x 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%,充分利用动态图像提供的不动产 .

    很酷,嗯?

    您可能需要稍微使用它来使其与您自己的设计一起使用,但这实际上对我来说效果非常好 . 一般的概念就在那里 .

  • -1

    艾略特激励我使用这个解决方案 - 谢谢:

    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);
    }
    

    Please note: background-size 是一个css3-feature可能无法与目标浏览器一起使用 . 您可以检查互操作性(f.e. on caniuse.com) .

  • 13

    要添加到Web_Designer的答案, <div> 将具有75%宽度 containing element 的高度(完全由底部填充组成) . 这是一个很好的总结:http://mattsnider.com/css-using-percent-for-margin-and-padding/ . 我'm not sure why this should be so, but that'是怎么回事 .

    如果您希望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;
    }
    

    我最近使用类似于Elliot的图像技巧,允许我使用CSS媒体查询根据设备分辨率提供不同的徽标文件,但仍按比例缩放,因为 <img> 自然会做(我将徽标设置为背景图像为透明 . png具有正确的宽高比) . 但是Web_Designer的解决方案会为我节省一个http请求 .

  • 0

    here on w3schools.com所述,并在accepted answer中有所重申,填充值为百分比(强调我的):

    以包含元素宽度的百分比指定填充

    Ergo,保持16:9宽高比的响应式DIV的正确示例如下:

    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>
    

    Demo on JSFiddle

  • 1

    基于你的解决方案,我已经做了一些技巧:

    当您使用它时,您的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 设置为高度/宽度即可 .

  • 2

    你可以使用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>
    

    请注意,内联svg似乎不起作用,但您可以对svg进行urlencode并将其嵌入到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%;" />
    
  • -1

    由于@ 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.25100:75 . 如果要先确保高度,则应切换宽度和高度,例如: height:100vh;width: calc(100vh * 9 / 16) 为9:16肖像 .

    如果您想要适应不同的屏幕尺寸,您可能也会感兴趣

    • background-size封面/包含

    • 以上样式类似于包含,取决于宽度:高度比 .

    • object-fit

    • 封面/包含img / video标签

    • @media (orientation: portrait) / @media (orientation: landscape)

    • portrait / landscape 的媒体查询更改比率 .

  • 6

    在我的案例中,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>
    

    source

  • 0

    这是对已接受答案的改进:

    • 使用伪元素而不是包装器div

    • The aspect ratio is based on the width of the box instead of its parent

    • 当内容变得更高时,框将垂直拉伸

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

    假设你有2个div,其他div是一个容器,内部可以是你需要保持其比例的任何元素(img或youtube 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 */
    }
    

    当以%指定时填充它是基于宽度而不是高度计算的 . ..所以基本上你无论你的宽度是多少,它的高度总是根据它来计算 . 这将保持比例 .

  • 1

    只是一个想法或一个黑客 .

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

    虽然大多数答案非常酷,但大多数答案要求图像已经正确尺寸...其他解决方案只适用于宽度而不关心可用的高度,但有时您也希望将内容放在一定高度 .

    我试图将它们结合在一起以带来一个完全可移植且可重新调整大小的解决方案......诀窍是使用自动缩放图像但使用内联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>
    

    请注意,我在SVG的宽度和高度属性中使用了较大的值,因为它需要大于最大预期大小,因为它只能缩小 . 该示例使div的比例为10:5

  • 3

    我已经遇到过这个问题很多次,所以我为它做了一个JS解决方案 . 这基本上根据元素的宽度按您指定的比例调整domElement的高度 . 你可以按照以下方式使用它:

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

    请注意,因为它设置了元素的高度,所以元素应该是 display:blockdisplay:inline-block .

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

  • 14

    如果你想在视口内放置纵向或横向视图中的正方形(尽可能大,但没有任何东西粘在外面),在方向 portrait / landscape 上使用 vw / vh 之间切换:

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

    您可以使用磁通布局(FWD) .

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

    它将扩展和维护布局,它有点复杂但允许页面调整大小而不像(RWD)那样推送内容 .

    它看起来像响应,但它正在扩展 . https://www.youtube.com/watch?v=xRcBMLI4jbg

    你可以在这里找到CSS缩放公式:

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

  • 1151

    假设您保持宽度:100px和高度:50px(即2:1)只需这样算:

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

    我使用 <svg>display:grid 偶然发现了a smart solution .

    Grid元素允许您使用两个(或更多)元素占用相同的空间,而无需指定哪个设置高度 . 这意味着,开箱即用, the taller one sets the ratio .

    这意味着你可以按原样使用它,当你知道内容永远不会高到足以填满整个"ratio"并且你只是想找到一种方法来在这个空间中定位内容(即在两个方向上居中使用 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;
    }
    

    您需要做的就是更改_659951的比例:

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

    如果您需要一个解决方案,其中内容元素不允许设置比例更高(溢出隐藏或自动),您需要在网格上设置 position:relative 并在内容上设置 position:absolute; height:100%; overflow-y: auto; . 例:

    .ratio {
      display: grid;
      position: relative;
    }
    .ratio > * {
      grid-area: 1/1/1/1;
    }
    
    
    .ratio > div {
      height: 100%;
      overflow-y: auto;
      position: absolute;
      
      /* the rest is not needed */
      border: 1px solid red;
      padding: 0 1rem;
    }
    
    <div class="ratio">
      <svg viewBox="0 0 7 1"></svg>
      <div>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. A scelerisque purus semper eget. Sem nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. A cras semper auctor neque vitae tempus quam pellentesque nec. Morbi enim nunc faucibus a pellentesque sit amet porttitor. Arcu odio ut sem nulla. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida neque. Cras tincidunt lobortis feugiat vivamus at augue eget. Laoreet sit amet cursus sit amet. Amet nulla facilisi morbi tempus iaculis urna id volutpat. Leo in vitae turpis massa sed elementum tempus egestas sed. Egestas integer eget aliquet nibh. Dolor sit amet consectetur adipiscing elit.
    
    <p>Ut aliquam purus sit amet. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Diam in arcu cursus euismod quis viverra nibh. Nullam vehicula ipsum a arcu cursus vitae congue. Vel orci porta non pulvinar neque laoreet suspendisse. At tellus at urna condimentum mattis pellentesque. Tristique senectus et netus et malesuada. Vel pretium lectus quam id leo in. Interdum velit euismod in pellentesque. Velit euismod in pellentesque massa placerat duis. Vitae suscipit tellus mauris a diam maecenas sed enim.
    
    <p>Mauris a diam maecenas sed enim ut sem. In hendrerit gravida rutrum quisque. Amet dictum sit amet justo donec enim diam. Diam vulputate ut pharetra sit amet aliquam id. Urna porttitor rhoncus dolor purus non enim praesent. Purus in massa tempor nec feugiat nisl pretium. Sagittis vitae et leo duis ut. Facilisi nullam vehicula ipsum a arcu cursus vitae congue mauris. Volutpat odio facilisis mauris sit amet massa vitae tortor condimentum. Aliquam purus sit amet luctus venenatis lectus magna. Sit amet purus gravida quis blandit turpis. Enim eu turpis egestas pretium aenean. Consequat mauris nunc congue nisi. Nunc sed id semper risus in hendrerit gravida rutrum. Ante metus dictum at tempor. Blandit massa enim nec dui nunc mattis enim ut.
      </div>
    </div>
    
  • 4

    如果整个容器结构是基于百分比的,这将是默认行为,您能提供更具体的示例吗?

    下面是我的意思的一个例子,如果你的整个父级层次结构是基于%的,任何浏览器窗口调整都可以在没有任何额外的js / css的情况下工作,这是不是你的布局的可能性?

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

    我用了一个新的解决方案 .

    .squares{
      width: 30vw
      height: 30vw
    

    主要宽高比

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

    但是,这与整个视口相关 . 因此,如果你需要一个占视口宽度30%的div,你可以改用30vw,因为你知道宽度,你可以使用calc和vw单位在高度上重复使用它们 .

相关问题