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

是否有任何CSS3规则允许高度根据宽度变化,同时保持其纵横比?

我知道我可以通过JavaScript做到这一点,但我更喜欢只使用CSS。


当前回答

我偶然发现了这个问题的聪明解决方案,使用<svg>和display:grid。

一个display:grid元素允许您使用相同的网格区域,与它的两个(或更多)子元素占据相同的空间。 这意味着它们都是流内容,重叠在一起,并且高的那个设定了比例。

其中之一是负责设置比率的<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;
}

将<svg>的比率设置为您想要的任何值:

<svg viewBox="0 0 4 3"></svg> . <svg viewBox="0 0 16 9"></svg> .

.ratio { 显示:网格; } .ratio > * { 网格:1/1; } /*下面的代码不需要设置比例 我只是想在视觉上做个标记 *和中心内容 * / .ratio div { 边框:1px纯红色; 显示:flex; 对齐项目:中心; justify-content:中心; } < div class = "比" > <svg viewBox="0 0 7 1"></svg> . < div > 固定比例7:1 < / div > < / div >


如果你需要一个解决方案,其中内容元素有更多的内容,你想要限制在一个滚动区域与期望的比例,设置位置:相对的父位置:绝对;高度:100%;overflow-y:汽车;在内容上,允许流内容元素(<svg>)设置大小,因此设置比率。

.ratio { 显示:网格; 位置:相对; } .ratio > * { 网格:1/1; } .ratio > div { 高度:100%; overflow-y:汽车; 位置:绝对的; /*其余部分不需要*/ 边框:1px纯红色; 填充物:0 1rem; } < div class = "比" > <svg viewBox="0 0 7 2"></svg> . < div > <h1>固定比例7:2</h1> <p>痛苦的痛苦,神圣的解脱,痛苦的痛苦和巨大的痛苦。一个永恒的灵魂。扫描光晕直径,坐与nisl,疑,adipiscisbendum。一个永远的主人,一个生命的时刻,一个心灵的灵魂。Morbi enim nunc faucibus一个漂亮的坐遇见porttitor。Arcu odio ut sem nulla。在分娩的过程中。克拉巧合的叶状裂片,在augue eget。老爷子和老爷子坐着。我不知道你在说什么。狮子座,在生命的turpis massa, tempus element, estestas。est整数eget aliquet nibh。多洛尔与神圣的精英们会面。 <p>但aliquam purus sit meet。Eget magna fermentum iaculis eu non diam phasellus vestibulum。这是我的命运,我的命运。剥夺权利,剥夺权利,剥夺生命。移动门,非枕边边,老窝悬挂。在tellus在urna condimentum mattis pellentesque。圣歌,圣歌,圣歌。这是一种很好的方法。皮朗式的夹缝。Velit euismod in pellentesque massa placerat duis。这是我的生命。 <p>Mauris a diam maecenas sed enim ut sem。在怀孕的过程中。我的格言是我的,我的灵魂是我的。Urna porttitor rhoncus dolus purus non enim present。下丘脑大炎,下丘脑大炎。生命之箭,狮子座之箭。对车辆的不作为权,对生命的不作为权。Volutpat odio facilisis mauris sit amet massa vitae tortorcondimentum。Aliquam purus sit at the luctus venenatis lectus magna。坐下来,感受孕妇的痛苦。Enim eu turpis eggestas pretium aenean。不可预知的后果。在怀孕初期,永远没有生气。言归正传。Blandit massa enim nec dui nunc mattis enim ut。 < / div > < / div >


正如@emjay在下面的评论中指出的那样,ratio svg可以放在父元素的一个伪元素中,只要它被正确编码:

.three-squares { 显示:网格; 边框:1px纯红色; } .three-squares > *, .three-squares:before { 网格:1/1; } .three-squares:{之前 content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 1'%3E%3C/svg%3E"); 行高:0; } < div class = "抢走”> < div >我3:1 < / div > < / div >

当在伪元素中使用时,<svg>成为一个替换的元素,默认情况下,它位于可变高度的基线上(Chrome中为4px, Firefox中为3.5px)。基线的高度根据行高而变化,这就是为什么我们需要在pseudo上设置line-height: 0以获得准确的比率。详情请点击这里。


我个人更喜欢将<svg>放在标记中的版本,因为我可以用一个类(.ratio)处理各种比率的容器(而不是为我可能需要的每个比率使用一个类)。

其他回答

只需创建一个包装器<div>,并为padding-bottom设置一个百分比值,如下所示:

.demoWrapper { 填充:10 px; 背景:白色; box-sizing: border-box; 调整:水平; 边框:1px虚线; 溢出:汽车; max-width: 100%; 高度:calc(100vh - 16px); } div { 宽度:100%; padding-bottom: 75%; 背景:黄金;/** <——用于演示**/ } < div class = " demoWrapper”> < div > < / 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%

在div中放置内容:

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

div.stretchy-wrapper {
  position: relative;
}

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

这里有一个演示和另一个更深入的演示

正如w3schools.com网站上所述,并在这个公认的答案中有所重申,填充值为百分比(重点是我的):

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

因此,一个保持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>

在JSFiddle上演示

Chrome 88的新特性是CSS的宽宽比属性,其他浏览器也很快会加入。

纵横比CSS属性为盒子设置了一个优先的纵横比,它将用于自动大小的计算和一些其他的布局功能。

CSS技巧文章

更多的信息

div { 背景:rebeccapurple; 身高:100 px; 保证金:1 em汽车; } .square { 纵横比:1 / 1; } < div class = "广场”> < / div >

我想只是使用rem或em应该解决固定比例的问题,但不会像vw或vh那样难以绑定到屏幕上,或者像%那样痛苦地使用flexbox。好吧,没有一个答案适合我,在我的情况下,这对我来说很重要:

<div class="container">
   <div>
   </div>
</div>
.container {
   height: 100vh;
   width: 100vw;
}
.container div {
   height: 4em;
   width: 3em;
}

或者用rem,但是不管怎样,它们中的任何一个都可以。 Rem使用默认的字体大小值,而em使用最接近的字体大小。

您可以使用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似乎不起作用,但你可以urlencode svg并将其嵌入到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%;" />