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

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

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


我已经找到了一种使用CSS来做到这一点的方法,但你必须小心,因为它可能会根据你自己网站的流程而变化。我这样做是为了在我的网站的流体宽度部分中嵌入具有恒定长宽比的视频。

假设你有一个这样的嵌入视频:

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

然后你可以把这些都放在一个带有“video”类的div中。这个视频类可能是你网站中的流动元素,它本身没有直接的高度限制,但当你调整浏览器的大小时,它会根据网站的流量改变宽度。这可能是你想要嵌入视频的元素,同时保持一定的视频宽高比。

为了做到这一点,我在“video”类div中的嵌入对象之前放了一张图像。

! !重要的部分是图像具有您希望保持的正确长宽比。此外,确保图像的大小至少与你期望的视频(或你正在维护的A.R.)根据你的布局得到的最小尺寸一样大。这将避免在调整百分比大小时图像分辨率中的任何潜在问题。例如,如果你想保持3:2的纵横比,不要只使用3px * 2px的图像。它在某些情况下可能会工作,但我还没有测试过,避免使用它可能是个好主意。

您可能已经为网站的流体元素定义了这样的最小宽度。如果没有,那么这样做是一个好主意,以避免在浏览器窗口变得太小时删除元素或出现重叠。在某些地方最好有一个滚动条。一个网页的最小宽度应该在600px左右(包括任何固定宽度的列),因为屏幕分辨率不能再小了,除非你处理的是手机友好型网站。! !

我使用一个完全透明的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%来充分利用动态图像提供的空间。

很酷,是吧?

您可能需要稍微摆弄一下才能让它与您自己的设计一起工作,但这实际上对我来说工作得非常好。大概的概念是这样的。


只需创建一个包装器<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;
}

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


为了补充Web_Designer的答案,<div>的高度(完全由底部填充组成)将是其包含元素宽度的75%。这里有一个很好的总结:http://mattsnider.com/css-using-percent-for-margin-and-padding/。我不知道为什么会这样,但事实就是这样。

如果你想让你的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媒体查询来根据设备分辨率提供不同的logo文件,但仍然按照<img>自然会做的比例缩放(我将logo作为背景图像设置为具有正确纵横比的透明。png)。但是Web_Designer的解决方案将为我节省一个http请求。


艾略特启发我想出了这个解决方案——谢谢:

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

请注意:background-size是css3特性,可能不适用于你的目标浏览器。你可以检查互操作性(f.e.在caniuse.com)。


根据你的解决方案,我做了一些技巧:

当您使用它时,您的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;
}

jQuery和jQuery

$('*[data-keep-ratio]').each(function(){ 
    var ratio = $(this).data('keep-ratio');
    $(this).css('padding-bottom', ratio);
});

有了这个,你只需要设置attr data-keep-ratio到高/宽,就这样。


有几种方法可以在元素(如div)上指定固定的纵横比,下面是其中的两种:

1. 纵横比CSS属性

div { 纵横比:1 / 1; 宽度:50%; 背景:蓝绿色; } <div>纵横比:1 / 1

这是最简单灵活的解决方案。它直接为元素指定固定的宽高比(或高宽比)。这意味着您还可以根据元素的高度指定纵横比。 它不依赖于父宽度(像填充技术)或视口大小(像下面的vw单元技术),它依赖于元素自身的宽度或高度。这就是为什么与其他变通方法相比,它是如此强大。

这是一个现代化的房产(2021年)。所有现代浏览器都支持它,请参阅caniuse以获得精确的浏览器支持。

下面是一些不同纵横比的例子:

.ar-1-1{纵横比:1 / 1;} .ar-3-2{纵横比:3 / 2;} .ar-4-3{纵横比:4 / 3;} .ar-16-9{纵横比:16 / 9;} .ar-2-3{纵横比:2 / 3;} .ar-3-4{纵横比:3 / 4;} .ar-9-16{纵横比:9 / 16;} /**对于演示:**/ 身体{ 显示:flex; flex-wrap:包装; 对齐项目:flex-start; } div { 背景:蓝绿色; 宽度:23%; 利润率:1%; 填充:20 px 0; box-sizing: border-box; 颜色:# fff; text-align:中心; } <div class="ar-1-1">纵横比:1 / 1 <div class="ar-3-2">纵横比:3 / 2 <div class="ar-4-3">纵横比:4 / 3 <div class="ar-16-9">纵横比:16 / 9 <div class="ar-2-3">纵横比:2 / 3 <div class="ar-3-4">纵横比:3 / 4 <div class="ar-9-16">纵横比:9 / 16

2. 使用大众单位:

你可以用vw单位来表示元素的宽度和高度。这允许根据视口宽度保留元素的纵横比。

Vw:视口宽度的百分之一。(MDN)

或者,你也可以使用vh作为视口高度,或者甚至使用vmin/vmax来使用视口尺寸中的较大/较小(此处讨论)。

例如:1:1的纵横比 div { 宽度:20大众; 高度:20大众; 背景:黄金; } < div > < / div >

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

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

示例:正方形div的4x4网格

身体{ 显示:flex; flex-wrap:包装; justify-content:之间的空间; } div { 宽度:23大众; 高度:23大众; 利润率:0.5大众汽车; 背景:黄金; } < 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 >

这里是一个摆弄这个演示,这里是一个解决方案,使一个响应网格的正方形与垂直和水平居中的内容。


浏览器对vh/vw单元的支持是IE9+,参见canIuse了解更多信息


正如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上演示


只是一个想法或黑客。

div { 背景颜色:蓝色; 宽度:10%; 过渡:底色0.5s,宽度0.5s; 字体大小:0; } div:{徘徊 宽度:20%; 背景颜色:红色; } img { 宽度:100%; 高度:汽车; 可见性:隐藏; } < div > <!—使用具有目标纵横比的图像。样本是一个正方形——> <img src="http://i.imgur.com/9OPnZNk.png" /> < / div >


我是这样做的:

[data-aspect-ratio] {
    display: block;
    max-width: 100%;
    position: relative;
}

[data-aspect-ratio]:before {
    content: '';
    display: block;
}

[data-aspect-ratio] > * {
    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>


我使用了一个新的解决方案。

.squares{
  width: 30vw
  height: 30vw

与主纵横比

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

然而,这是相对于整个视口而言的。所以,如果你需要一个div是视口宽度的30%,你可以使用30vw代替,因为你知道宽度,你可以使用calc和vw单位在高度上重用它们。


假设你有2个div,外部的div是一个容器,内部的div可以是你需要保持其比例的任何元素(img或YouTube iframe或其他)

HTML看起来是这样的:

<div class='container'>
  <div class='element'>
  </div><!-- end of element -->
<div><!-- end of container -->

比如说你需要保持元素的比例 比例=> 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 */
}

当在%中指定填充时,它是基于宽度而不是高度计算的。 .. 所以基本上,不管你的宽是多少,高总是以此为基础计算出来的。这样就能保持比例不变。


您可以使用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%;" />

虽然大多数答案都很酷,但大多数都要求已经正确大小的图像……其他解决方案只适用于宽度,而不关心可用的高度,但有时您也希望将内容适应于特定的高度。

我试图将它们组合在一起,以带来一个完全可移植和可调整大小的解决方案……诀窍是使用自动缩放图像,但使用内联svg元素,而不是使用预渲染的图像或任何形式的第二个HTTP请求…

div.holder { 背景颜色:红色; 显示:inline-block; 身高:100 px; 宽度:400 px; } svg img { 背景颜色:蓝色; 显示:块; 高度:汽车; 宽度:汽车; max-width: 100%; max-height: 100%; } .content_sizer { 位置:相对; 显示:inline-block; 高度:100%; } .content { 位置:绝对的; 上图:0; 底部:0; 左:0; 右:0; background - color: rgba(155255年,0,0.5); } < div class = "架" > < div class = " content_sizer”> <svg width=10000 height=5000 /> < div class = "内容" > < / div > < / div > < / div >

请注意,我在SVG的width和height属性中使用了较大的值,因为它需要大于预期的最大大小,因为它只能缩小。这个例子使div的比例为10:5


我遇到过这个问题很多次,所以我为它做了一个JS解决方案。这基本上是根据你指定的元素宽度比例来调整domElement的高度。你可以这样使用它:

<格比=“4x3”></div>

请注意,因为它正在设置元素的高度,元素应该是一个display:block或display:inline-block。

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


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

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

由于@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)为溢流高度,因此,拉升溢流高度/2将使其保持在屏幕中心。

为风景,并保持16:9,你显示使用

.container {
  width: 100vw;
  height: calc(100vw * 9 / 16);
  transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}

9/16的比例很容易改变,不需要预定义100:56.25或100:75。如果你想先保证高度,你应该切换宽度和高度,例如:高度:100vh;宽度:calc(100vh * 9 / 16) 9:16纵向。

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

background-size封面/包含 上面的样式类似于包含,取决于宽高比。 object-fit img/video标签的封面/包含 @media(朝向:纵向)/@media(朝向:横向) 媒体查询肖像/风景改变比例。


这是对公认答案的改进:

使用伪元素而不是包装器div 长宽比基于盒子的宽度,而不是它的父元素 当内容变高时,盒子会垂直拉伸

.box { margin-top: 1 em; margin-bottom: 1 em; background - color: # CCC; } {前.fixed-ar:: 内容:“”; 浮:左; 宽度:1 px; margin-left: 1 px; } {后.fixed-ar:: 内容:“”; 显示:表; 明确:; } {前.fixed-ar-16-9:: padding-top: 56.25%; } {前.fixed-ar-3-2:: padding-top: 66.66%; } {前.fixed-ar-4-3:: padding-top: 75%; } {前.fixed-ar-1-1:: padding-top: 100%; } .width-50 { 显示:inline-block; 宽度:50%; } .width-20 { 显示:inline-block; 宽度:20%; } <div class="box - fixed-ar- ar-16-9">16:9 full width</div> <人力资源> <div class="box - fixed-ar- ar-16-9 width-50">16:9</div> <人力资源> <div class="box - fixed-ar- ar-16-9 width-20">16:9</div> <div class="box - fixed-ar-3-2 width-20">3:2</div> <div class="box - fixed-ar-4-3 width-20">4:3</div> <div class="box - fixed-ar-1-1 width-20">1:1</div> <人力资源> <div class="box - fixed-ar- ar-16-9 width-20">16:9</div> <div class="box - fixed-ar- ar-16-9 width-50">16:9</div>


假设你想保持宽度:100px和高度:50px(即2:1) 算一下:

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

我偶然发现了这个问题的聪明解决方案,使用<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)处理各种比率的容器(而不是为我可能需要的每个比率使用一个类)。


我想分享我的解决方案,其中我有一个img-tag填充一定的纵横比。我不能使用背景,因为缺乏对CMS的支持,我不喜欢使用这样的样式标签:<img style="background:url(…)"/ >。此外,宽度为100%,因此不需要像某些解决方案那样设置为固定大小。它将响应伸缩!

.wrapper { 宽度:50%; } .image-container { 位置:相对; 宽度:100%; } {前.image-container:: 内容:“”; 显示:块; } .image-container img { 位置:绝对的; 上图:0; 左:0; 宽度:100%; 高度:100%; object-fit:封面; } {前.ratio-4-3:: padding-top: 75%; } {前.ratio-3-1:: 填充顶:calc(100% / 3); } {前.ratio-2-1:: padding-top: 50%; } <div class="wrapper"> <!——让事情变得小一点——> < p > 一个4:3宽高比的例子,由一个1:1比例的图像填充。 < / p > <div class="image-container ratio-4-3"> <!——让我们用4:3的长宽比——> <img src="https://placekitten.com/1000/1000/" alt="小猫!"/> < / div > < p > 只需在它周围放置其他块元素;它会工作得很好。 < / p > < / div >


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

这要视情况而定,但在某些情况下它真的很有用。举个例子,你可以设置background-image而不设置固定的高度,或者用它来嵌入youtube <iframe>,比例为16:9,位置:绝对等。

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

例子:

div { 背景颜色:红色 } svg { 宽度:100%; 显示:块; 可见性:隐藏 } .demo-1{宽度:35%} .demo-2{宽度:20%} < div class = " demo-1”> <svg viewBox="0 0 3 2"></svg> . < / div > <人力资源> < div class = " demo-2”> <svg viewBox="0 0 3 2"></svg> . < / div >


保持纵横比的一个简单方法,使用canvas元素。

尝试调整下面的div的大小,看看它的作用。

对我来说,这种方法效果最好,所以我把它分享给其他人,这样他们也能从中受益。

.cont { 边框:5px纯蓝色; 位置:相对; 宽度:300 px; 填充:0; 保证金:5 px; 调整:水平; 溢出:隐藏; } .ratio { 宽度:100%; 保证金:0; 显示:块; } .content { Background-color: rgba(255, 0,0, 0.5); 位置:绝对的; 上图:0; 左:0; 宽度:100%; 高度:100%; 保证金:0; } < div class = "跟" > <canvas class="ratio" width="16" height="9"></canvas> <div class="content">我是16:9</div> < / div >

也适用于动态高度!

.cont { 边框:5px纯蓝色; 位置:相对; 身高:170 px; 填充:0; 保证金:5 px; 调整:垂直; 溢出:隐藏; 显示:inline-block;/*所以div不会自动扩展到最大宽度*/ } .ratio { 高度:100%; 保证金:0; 显示:块; } .content { Background-color: rgba(255, 0,0, 0.5); 位置:绝对的; 上图:0; 左:0; 宽度:100%; 高度:100%; 保证金:0; } < div class = "跟" > <canvas class="ratio" width="16" height="9"></canvas> <div class="content">我是16:9</div> < / div >


2021年更新- CSS纵横比属性

我们最近获得了在CSS中使用长宽比属性的能力。

https://twitter.com/Una/status/1260980901934137345/photo/1

注意:支持还不是最好的…

注意:支持是相当体面的!

https://caniuse.com/#search=aspect-ratio

编辑:长宽比现在可用!

https://web.dev/aspect-ratio/

如果你对如何使用它感兴趣,可以看看下面这个超级简单的例子

    .yourClass {
       aspect-ratio: 4/3;
    }

这里是我的解决方案,以保持16:9纵横比在纵向或横向的div与可选的固定边距。

它是宽度/高度和最大宽度/最大高度属性与vw单位的组合。

在这个示例中,悬停时添加了50px的上下边距。

html { 高度:100%; } 身体{ 保证金:0; 高度:100%; } .container { 显示:flex; justify-content:中心; 对齐项目:中心; 高度:100%; } .fixedRatio { max-width: 100大众; Max-height: calc(9 / 16 * 100vw); 宽度:calc(16 / 9 * 100vh); 身高:100 vh; /*调试*/ 显示:flex; justify-content:中心; 对齐项目:中心; 背景颜色:蓝色; 字体大小:2快速眼动; 字体类型:“天线”; 颜色:白色; 过渡:宽度0.5s进出,高度0.5s进出; } .fixedRatio:{徘徊 宽度:calc(16 / 9 * (100vh - 100px)); 高度:calc(100vh - 100px); } < div class =“容器”> < div class = ' fixedRatio ' > 16:9 < / div > < / div >

在JSFiddle上演示


2020解决方案-使用网格和填充伪元素

我找到了一些更新颖的方法来破案。该解决方案是any填充底部方法的后代,但没有任何位置:绝对子方法,只使用display: grid;和伪元素。

这里我们有。ratio::before,填充底部:XX%,网格区域:1 / 1 / 1 / 1;,这迫使伪元素保持在网格中的位置。虽然这里我们有width: 0;为了防止主元素被这个索引溢出(我们在这里冷地使用z-index,但是这个索引更短)。

我们的主元素。ratio > *:first-child与。ratio::之前的位置相同,即grid-area: 1 / 1 / 1 / 1;,因此它们共享相同的网格单元格位置。现在我们可以在div中放入任何内容,而pseudo元素是决定宽高比的元素。更多关于网格区域。

.ratio { 显示:网格; grid-template-columns: 1 fr; max-width: 200 px;例如,/*可以是100%,取决于父*/ } {前.ratio:: 内容:”; 宽度:0; 填充底:calc(100% / (16/9));/*在这里你可以放置任何比例*/ 网格面积:1 / 1 / 1 / 1; } .ratio > *:第一个孩子{ 网格面积:1 / 1 / 1 / 1;/*与*/前的::相同 背景:rgba(0,0,0,0.1);例如*/ } < div class = "比" > 16/9 < div > < / div > < / div >


虽然你可以使用cssval并使用样式属性将比值放在HTML中。工作与显示:内联网格以及。

.ratio { 显示:inline-grid; grid-template-columns: 1 fr; 宽度:200 px;例如,/*可以是100%,取决于父*/ margin-right: 10 px;例如*/ } {前.ratio:: 内容:”; 宽度:0; 填充底部:calc(100% / (var(—r)));/*在这里你可以放置任何比例*/ 网格面积:1 / 1 / 1 / 1; } .ratio > *:第一个孩子{ 网格面积:1 / 1 / 1 / 1;/*与*/前的::相同 背景:rgba(0,0,0,0.1);例如*/ } <div class="ratio" style="——r: 4/3;"> < div > 4/3 < / div > < / div > <div class="ratio" style="——r: 16/9;"> 16/9 < div > < / div > < / div >


我刚刚创建了一个2:1的div,调整大小以占据全宽度,但如果它会导致顶部或底部超过,则会缩小宽度。但是请注意,这只适用于窗口的大小,而不是父窗口的大小。

#scene {
    position: relative;
    top: 50vh;
    left: 50vw;
    width: 100vw;
    height: 50vw;
    max-height: 100vh;
    max-width: calc(100vh * 2);
    transform: translate(-50%, -50%);
}

我相信你可以计算出正确的%,用于4:3而不是2:1。


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

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

CSS技巧文章

更多的信息

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


我想分享这一点,因为这是一段令人沮丧的几天的旅程,找到了一个适合我的解决方案。我使用这些填充技术(上面提到过使用一些填充和绝对定位的变化)来为网格/flex布局中的按钮类元素实现1:1的纵横比。布局设置为100vh高,以便始终显示为单个非滚动页面。

填充技术确实工作得很好,但它很容易破坏你的网格布局,并导致爆炸性/讨厌的滚动条。在这种情况下,那些说绝对div不会影响布局的人是错误的,因为父元素在高度和宽度上都在增长,即使子元素没有直接影响布局,父元素也会扰乱你的布局。

通常这不是问题,但在使用网格时需要注意。网格是一个2D布局,它可以在两个轴上考虑大小和布局。我仍然试图理解这的确切性质,但到目前为止,似乎至少如果你在一个网格区域内使用这种技术,在两个轴上都受到fr单位的限制,当纵横比项增长或以其他方式改变布局时,你几乎肯定会遇到井喷(显示:无切换和交换网格区域与css也是布局变化问题,导致我的井喷)。

在我的例子中,我限制了一个不需要的列的高度。将其改为“auto”而不是“1fr”,使我所有的其他布局保持不变,防止井喷,同时仍然让我保持我漂亮的方形按钮!

我不知道这是否是这里每个人沮丧的来源,但这是一个很容易犯的错误,即使使用开发工具也不能让你准确地知道井喷来自哪里,因为在许多情况下,它并不是一个单独的元素井喷出来的情况,而是网格布局扩大自己,以保持那些fr单位在垂直和水平上的准确。


2022解决方案-使用CSS的纵横比属性

<div class='demo'></div>
.demo {
  background: black;
  width: 500px;
  aspect-ratio: 4/3;
}

更新:现在所有常绿浏览器都支持这个解决方案


我想只是使用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使用最接近的字体大小。


感谢大家的贡献,我将在这里添加我的解决方案,这主要是通过重复已接受的答案来实现的。我喜欢这种方法的主要原因是没有不必要的DOM,因为我在填充之前使用:。

@card-standard-line-height: 21px;
@card-standard-title-line-height: 22.5px;
@16to9percentage: 56.25%;

.overflow {
  background-color: inherit;
  /* stylelint-disable property-no-unknown */
  box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-box-orient: vertical;
  /* stylelint-enable */
  color: inherit;
  display: box;
  display: -webkit-box;
  display: -moz-box;
  max-width: 100%;
  overflow: hidden;
  position: relative;
  text-overflow: -o-ellipsis-lastline;
  text-overflow: ellipsis;
}

* {
  box-sizing: border-box;
}

body {
  padding: 2rem;
}

.card {
  color: #fff;
  height: auto;
  max-width: 100%;
  min-width: unset;
  position: relative;
  
  h2 {
    font: 18px / 22.5px bold;
  }
  
  p {
    font: 14px / 21px normal;
  }

  &-16to9 {
    .badge {
      color: white;
      display:flex;
      background-color: red;
      justify-content: baseline;
      padding: 16px 32px 12px 16px;
      position: absolute;
      right: 0;
      top: 16px;
      z-index: 2;
      span {
        font: 14px / 14px bold;
      }
    }
    // look at this https://css-tricks.com/aspect-ratio-boxes/
    .card {
      &_description {
        max-height: @card-standard-line-height * 1;
        // Number of allowable lines in layout
        -webkit-line-clamp: 1;
      }

      &_image,
      &_info {
        bottom: 0;
        height: 100%;
        max-height: 100%;
        min-height: 100%;
        left: 0;
        position: absolute;
        right: 0;
        top: 0;
        z-index: 0;
      }

      &_info {
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        padding: 24px;
        z-index: 2;
      }

      &_title {
        max-height: @card-standard-title-line-height * 2;
        // Number of allowable lines in layout
        -webkit-line-clamp: 2;
      }
    }

    &:after,
    &:before {
      content: "";
      display: block;
    }

    &:after {
      background: rgba(0, 0, 0, 0);
      background: linear-gradient(0deg, rgba(0, 0, 0, 1) 16%, rgba(0, 0, 0, 0) 100%);
      bottom: 0;
      height: 100%;
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: 1;
    }

    &:before {
      padding-bottom: @16to9percentage;
    }
  }
}

https://codepen.io/augur/pen/GRNGLZv?editors=0100


CSS对此有一个新的属性:aspect-ratio。

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

@supports(纵横比:1 / 1){ div { 纵横比:16 / 9; 背景颜色:橙色; } } <div style="width: 200px"></div> . <人力资源/ > <div style="width: 400px"></div> . <人力资源/ > <div style="height: 50px"></div> . <人力资源/ > <div style="height: 10px"></div> .

Chrome和Edge从V88开始完全支持它,Firefox从V81开始支持它(设置layout.css.aspect-ratio。在about:config中启用为true)。

兼容性信息请访问https://caniuse.com/mdn-css_properties_aspect-ratio


container {
   height: 100vh;
   width: 100vw;
}
.container div {
   height: 4em;
   width: 3em;
}

实际上,高投票的答案是一个非常好的解决方案,但有一个新的CSS功能,名字是长宽比。

它可以这样使用:

.someClass {
  width: 100%;
  aspect-ratio: 4/3;
}

自动确定高度,但请参见兼容性表:

如果浏览器支持对你的项目很重要,不要使用它。使用填充底技术。


新的纵横比标签会很棒,但它打乱了我的divs的定位。 填充包装器div的传统解决方案是有效的,但只能根据父类或视口的宽度调整大小,当高度是限制因素时,这就产生了问题。

我发现min()函数非常有用,并调整了传统的方法,如下所示:

身体{ background-image: linear-gradient(到右上,#FFE6B5, #B3CEBF); 填充:0; 保证金:0自动; overflow-y:隐藏;/*这是为了避免在视口高度小于纵横比要求*/时滚动 } .wrapper { 位置:相对; 宽度:100大众; max-height: 100 vh; } .sixteen-by-nine。宽高比{ 衬底:56.25% /* 9:16比*/ } .content { 位置:绝对的; 上图:0;底部:0;左:0;右:0; 背景颜色:绿色 } .centered { 位置:绝对的; 左:50%; 上图:50%; 转换:翻译(-50%,-50%); 高度:100%; 宽度:min(177.8vh, 100%);/*这总是在视口中保持16:9的比例*/ 字体大小:最小(1.7 3 vh,大众);/*如果你也对缩放字体大小*/感兴趣 背景颜色:蓝色 } 身体< > < div class = "包装" > <div class=" 16x9纵横比"></div> <div class="content" > < div class = "集中" > <!——东西在这里——> < / div > < / div > < / div > 身体< / >


我们是这样解决的:

.square {
  width: 100%;
  max-height: 100%;
  aspect-ratio: 1;
  background: red;
  position: relative;
  margin: auto;
  top: 50%;
  transform: translateY(-50%);
}

参见https://jsfiddle.net/r1jL3oqa/1/


在Angular中,我添加了一个处理纵横比的指令。

import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from 
"@angular/core";
import { debounceTime, fromEvent, Subject, takeUntil } from "rxjs";
 
// Auto sets the height of element based on width. Also supports window resize
@Directive({
    selector: '[aspectRatio]'
})
export class AspectRatioDirective implements AfterViewInit {
    @Input() aspectRatio?: number; // example 9/16

    private readonly onDestroy$ = new Subject<void>();

    constructor(private element: ElementRef, private renderer: Renderer2) {}

    public ngAfterViewInit(): void {
        this.setDimensions();
        this.initResizeListeners();
    }

    public ngOnDestroy(): void {
        this.onDestroy$.next();
        this.onDestroy$.complete();
      }

    private setDimensions(): void {
        if (!this.aspectRatio) { return; }
        const width = this.element.nativeElement.clientWidth;
        this.renderer.setStyle(this.element.nativeElement, 'height', `${width * this.aspectRatio}px`);
    }

    private initResizeListeners(): void {
        fromEvent(window, 'resize')
          .pipe(debounceTime(100), takeUntil(this.onDestroy$))
          .subscribe(() => this.setDimensions());
      }
}