关于html:用CSS保持div的宽高比

Maintain the aspect ratio of a div with CSS

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

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

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

div keeping aspect ratio according to width of window


只需使用padding-bottom的百分比值创建一个包装器,如下所示:

1
2
3
4
5
div {
  width: 100%;
  padding-bottom: 75%;
  background: gold; /** <-- For the demo **/
}
1
 

它将产生一个高度等于容器宽度75%(4:3宽高比)的

这取决于填充:

The percentage is calculated with respect to the width of the generated box's containing block [...] (source: w3.org, emphasis mine)

填充其他纵横比和100%宽度的底值:

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

在分区中放置内容:

为了保持DIV的纵横比并防止其内容拉伸它,需要添加一个绝对定位的子级,并使用以下方法将其拉伸到包装的边缘:

1
2
3
4
5
6
7
8
div.stretchy-wrapper {
  position: relative;
}

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

这是一个演示和另一个更深入的演示


vw台:

可以对元素的宽度和高度使用vw单位。这允许根据视区宽度保留元素的纵横比。

vw : 1/100th of the width of the viewport. [MDN]

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

示例:1:1纵横比

1
2
3
4
5
div {
  width: 20vw;
  height: 20vw;
  background: gold;
}
1
 

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

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

示例:4x4方形分隔网格

1
2
3
4
5
6
7
8
9
10
11
body {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
div {
  width: 23vw;
  height: 23vw;
  margin: 0.5vw auto;
  background: gold;
}
1
 

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

vh/vw单元的浏览器支持是ie9+,更多信息请参见caniuse。


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

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

1
2
3
4
<object>
     <param ... /><param ... />...
     
</object>

然后你可以把这些都放在一个带有"视频"类的分区中。这个视频类可能是网站中的流体元素,因此它本身没有直接的高度限制,但是当您调整浏览器的大小时,它将根据网站的流改变宽度。这可能是您在保持视频的某个纵横比的同时,试图嵌入视频的元素。

为了做到这一点,我在"video"类中的嵌入对象之前放置了一个图像。

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

您可能已经为网站的流体元素定义了这样的最小宽度。如果不是,最好这样做,以避免在浏览器窗口太小时截断元素或重叠元素。最好在某个时刻有一个滚动条。网页的最小宽度应该是大约600像素(包括任何固定宽度的列),因为屏幕分辨率不会变小,除非你处理的是对电话友好的网站。!!!!

我使用了一个完全透明的PNG,但如果你做的对,我不认为它最终会有什么影响。这样地:

1
2
3
4
5
     <img class="maintainaspectratio" src="maintainaspectratio.png" />
     <object>
          <param ... /><param ... />...
         
     </object>

现在,您应该能够添加类似于以下内容的CSS:

1
2
3
4
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%,充分利用动态图像提供的不动产。

很酷,嗯?

为了让它与你自己的设计一起工作,你可能需要在它周围玩一玩,但这对我来说确实非常好。总的概念就在那里。


为了增加web_设计师的答案,的高度(完全由底部填充物组成)为包含元素宽度的75%。下面是一个很好的总结:http://mattsnider.com/css,使用百分比作为边距和填充。我不知道为什么会这样,但事实就是这样。

如果希望DIV的宽度不是100%,则需要另一个包装DIV来设置宽度:

1
2
3
4
5
6
7
8
9
10
11
12
13
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媒体查询根据设备分辨率为不同的徽标文件提供服务,但仍然按比例缩放,因为自然会这样做(我将徽标设置为具有正确纵横比的透明.png背景图像)。但是Web_Designer的解决方案会为我保存一个HTTP请求。


艾略特启发我去解决这个问题-谢谢:

aspectratio.png是一个完全透明的png文件,其大小与您的首选纵横比相同,在我的例子中是30x10像素。

HTML

1
  <img src="/img/aspectratio.png"/>

CSS3

1
2
3
4
5
6
.eyecatcher img {
  width: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url(../img/autoresized-picture.jpg);
}

请注意:background-size是一个CSS3功能,可能不适用于您的目标浏览器。您可以检查互操作性(canius.com上的f.e.)。


如w3schools.com上所述,在这个公认的答案中有点重复,将值填充为百分比(强调我的):

Specifies the padding in percent of the width of the containing element

因此,保持16:9纵横比的响应DIV的正确示例如下:

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.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

1
        Aspect is kept when resizing

JSfiddle演示


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

当您使用它时,您的HTML将仅

1
    Main content

要这样使用,请执行以下操作:CSS:

1
2
3
4
5
6
7
8
9
10
11
12
*[data-keep-ratio] {
    display: block;
    width: 100%;
    position: relative;
}
*[data-keep-ratio] > * {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

和JS(jQuery)

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

有了这个,你只需要把data-keep-ratio设为高度/宽度,就这样了。


这是对公认答案的改进:

  • 使用伪元素而不是包装分隔符
  • 纵横比基于框的宽度而不是其父框的宽度。
  • 当内容变高时,框将垂直拉伸。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
.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%;
}
1
2
3
4
5
6
7
8
9
10
11
16:9 full width

16:9

16:9
3:2
4:3
1:1

16:9
16:9


由于@web tiki已经展示了一种使用vhvw的方法,我还需要一种在屏幕中居中的方法,这里是一个9:16纵向的代码片段。

1
2
3
4
5
.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,你显示使用

1
2
3
4
5
.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的纵向。

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

  • 背景尺寸封面/封面
    • 上面的样式类似于contain,取决于宽高比。
  • 对象拟合
    • 图像/视频标签的封面/封套
  • @media (orientation: portrait)/@media (orientation: landscape)
    • 媒体查询portrait/landscape以更改比率。


你可以使用SVG。使容器/包装器位置相对,首先将SVG置于静态位置,然后放置绝对位置的内容(顶部:0;左侧:0;右侧:0;底部:0;)

16:9比例示例:

image.svg:(可以在src中内联)

1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 9" width="16" height="9"/>

CSS:

1
2
3
4
5
6
7
.container {
  position: relative;
}
.content {
  position: absolute;
  top:0; left:0; right:0; bottom:0;
}

HTML:

1
  <img style="width: 100%" src="image.svg" />

请注意,内联svg似乎不起作用,但您可以对svg进行urlencode并将其嵌入img-src属性,如下所示:

1
<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%;" />

在我的例子中,SCSS是最好的解决方案;使用数据属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
[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%;
}

例如:

1
<iframe ...></iframe>

来源


假设你有两个div,外部的div是一个容器,内部可能是任何你需要保持其比率的元素(img或youtube iframe或其他什么)。

HTML如下所示:

1
  <!-- end of element -->

假设您需要保持"元素"的比率

比率=>4比1或2比1…

CSS看起来像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
1
2
  <!-- use an image with target aspect ratio. sample is a square -->
  <img src="http://i.imgur.com/9OPnZNk.png" />


虽然大多数答案都很酷,但大多数答案都要求图像大小正确…其他解决方案只适用于宽度,不考虑可用的高度,但有时您也希望将内容调整到一定的高度。

我试着将它们结合在一起,以提供一个完全可移植的、可重新调整大小的解决方案…技巧是使用自动缩放图像,但使用内联SVG元素而不是使用预渲染图像或任何形式的第二个HTTP请求…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
}
1
    <svg width=10000 height=5000 />

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


我偶然发现了一个使用display:grid的智能解决方案。

网格元素允许您使用两个(或更多)元素占用同一空间,而无需指定哪个元素设置高度。也就是说,开箱即用越高的设定比率。

这意味着,当你知道内容永远不会高到足以填满整个"比例"时,你可以按原样使用它,而你只是在寻找一种方法来定位此空间中的内容(即,将内容集中在两个方向上使用display:flex; align-items:center; justify-content:center。这与使用透明的display:block和预先确定的比率基本相同,但更轻,更容易修改(如果需要,可以相应地更改比率)。

1
2
3
  <svg viewBox="0 0 1 1"></svg>
 
    I'm square
1
2
3
4
5
6
.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

您只需更改的比率:

看到它工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.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;
}
1
2
3
  <svg viewBox="0 0 7 1"></svg>
 
    Fixed ratio 7:1

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.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;
}
1
2
3
4
5
6
7
8
9
10
  <svg viewBox="0 0 7 1"></svg>
 
    <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.


我经常遇到这个问题,所以我为它设计了一个JS解决方案。这基本上是根据元素的宽度,按您指定的比例调整domElement的高度。您可以使用它,如下所示:

请注意,由于它设置了元素的高度,元素应该是display:blockdisplay:inline-block

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


如果您想在人像或风景视图(尽可能大,但没有东西贴在外面)的视区内放置一个正方形,请在方向portrait/landscape上使用vw/vh切换:

1
2
3
4
5
6
7
8
9
10
11
12
@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
}
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
}

您可以使用通量布局(fwd)。

https://en.wikipedia.org/wiki/adaptive_web_设计

它将缩放和维护布局,虽然有点复杂,但允许页面调整大小,而不必像(rwd)那样推送内容。

它看起来像是响应的,但它是可伸缩的。https://www.youtube.com/watch?V= XRCBMLI4JBG

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

Flux Web Design Layout (FWD) & Zoom Web Design Layout (ZWD)


假设你保持宽度:100px,高度:50px(即2:1)只需计算一下:

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


我用了一种新的解决方案。

1
2
3
.squares{
  width: 30vw
  height: 30vw

主展弦比

1
2
3
.aspect-ratio
  width: 10vw
  height: 10vh

但是,这是相对于整个视区的。因此,如果您需要一个占视区宽度30%的DIV,您可以使用30VW,因为您知道宽度,所以可以使用CALC和VW单位在高度上重用它们。


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

下面是一个例子,我的意思是,如果您的整个父层次结构是基于%的,那么任何浏览器窗口调整都可以在没有任何额外的JS/CSS的情况下工作,这对您的布局来说不是可能的吗?

1
   Content