1283

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

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

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

div根据窗口宽度保持纵横比

4

37 回答 37

1516

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

.demoWrapper {
  padding: 10px;
  background: white;
  box-sizing: border-box;
  resize: horizontal;
  border: 1px dashed;
  overflow: auto;
  max-width: 100%;
  height: calc(100vh - 16px);
}

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

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

于 2012-05-04T01:19:53.813 回答
485

有几种方法可以在像 div 这样的元素上指定固定的纵横比,这里有两种方法:

1. aspect-ratioCSS 属性

div {
  background: teal;
  width: 50%;
  aspect-ratio: 1 / 1;
}
<div>aspect-ratio: 1 / 1;</div>

这是最简单灵活的解决方案。它直接指定元素的固定宽高比(或高宽比)。这意味着您还可以根据元素高度指定纵横比。
它不依赖于父宽度(如填充技术)或视口大小(如以下vw单元技术)它依赖于元素自己的宽度或高度MDN 上的更多信息。与其他解决方法相比,这就是它如此强大的原因。

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

以下是一些具有不同纵横比的示例:

.ar-1-1  {aspect-ratio: 1 / 1;}
.ar-3-2  {aspect-ratio: 3 / 2;}
.ar-4-3  {aspect-ratio: 4 / 3;}
.ar-16-9 {aspect-ratio: 16 / 9;}
.ar-2-3  {aspect-ratio: 2 / 3;}
.ar-3-4  {aspect-ratio: 3 / 4;}
.ar-9-16 {aspect-ratio: 9 / 16;}


/** For the demo : **/
body {
  display:flex;
  flex-wrap:wrap;
  align-items:flex-start;
}
div {
  background: teal;
  width: 23%;
  margin:1%;
  padding:20px 0;
  color:#fff;
  text-align:center;
}
<div class="ar-1-1">aspect-ratio: 1 / 1;</div>
<div class="ar-3-2">aspect-ratio: 3 / 2;</div>
<div class="ar-4-3">aspect-ratio: 4 / 3;</div>
<div class="ar-16-9">aspect-ratio: 16 / 9;</div>
<div class="ar-2-3">aspect-ratio: 2 / 3;</div>
<div class="ar-3-4">aspect-ratio: 3 / 4;</div>
<div class="ar-9-16">aspect-ratio: 9 / 16;</div>

2、使用vw单位:

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

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

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

示例: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>

Here is a Fiddle with this demo这是一个解决方案,用于制作具有垂直和水平居中内容的响应式正方形网格


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

于 2014-05-15T08:48:00.433 回答
105

2021 解决方案 - 使用aspect-ratioCSS 属性

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

不同浏览器的属性支持

于 2021-02-23T14:38:40.350 回答
63

我偶然发现了我认为解决这个问题的聪明方法,使用<svg>and display:grid.

一个display:grid元素允许您使用相同的grid-area.
这意味着它们都是流动的内容,重叠的,并且开箱即用,较高的设置比率

其中一位将<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>s 比率设置为您想要的任何值:

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

.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 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;内容上进行设置,允许流内容元素(<svg>)设置大小,从而设置比例。

.ratio {
  display: grid;
  position: relative;
}
.ratio > * {
  grid-area: 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 2"></svg>
  <div>
    <h1>Fixed ratio 7:2</h1>
    <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>


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

.three-squares {
  display: grid;
  border: 1px solid red;
}

.three-squares > *, .three-squares:before {
  grid-area: 1/1;
}

.three-squares:before {
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 1'%3E%3C/svg%3E");
  line-height: 0;
}
<div class="three-squares">  
  <div>I'm 3:1</div>
</div>

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


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

于 2018-11-11T03:44:22.117 回答
28

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

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

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

然后,您可以将它们全部放在带有“视频”类的 div 中。这个视频类可能是您网站中的流体元素,因此它本身没有直接的高度限制,但是当您调整浏览器的大小时,它的宽度会根据网站的流量发生变化。这将是您可能试图在保持视频的特定纵横比的同时获取嵌入视频的元素。

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

!!!重要的是图像具有您希望保持的正确纵横比。此外,请确保图像的大小至少与您期望视频(或您维护 AR 的任何内容)根据您的布局获得的最小一样大。这将避免在按百分比调整大小时图像分辨率中的任何潜在问题。例如,如果您想保持 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% 来充分利用动态图像提供的空间。

很酷,嗯?

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

于 2009-12-22T02:08:49.027 回答
20

Elliot 启发了我这个解决方案 - 谢谢:

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

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

于 2012-07-07T14:25:42.200 回答
17

w3schools.com 上的此处所述,并在此接受的答案中有所重申,填充值作为百分比(强调我的):

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

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>

JSFiddle 上的演示

于 2015-03-22T12:18:17.970 回答
17

由于@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纵向。

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

  • 背景大小的封面/包含
    • 上面的样式类似于包含,取决于宽高比。
  • 对象拟合
    • 封面/包含 img/video 标签
  • @media (orientation: portrait)/@media (orientation: landscape)
    • portrait用于/landscape更改比率的媒体查询。
于 2017-11-01T02:40:25.090 回答
16

添加到 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 媒体查询来根据设备分辨率提供不同的徽标文件,但仍然按比例缩放<img>(我将徽标设置为背景图像为透明 .png具有正确的纵横比)。但是 Web_Designer 的解决方案可以为我节省一个 http 请求。

于 2012-05-06T17:35:13.990 回答
14

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

  • 使用伪元素而不是包装 div
  • 纵横比基于框的宽度而不是其父级
  • 当内容变高时,盒子会垂直拉伸

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

于 2018-07-03T10:20:22.647 回答
12

2021 更新 - CSS纵横比属性

好吧,我们最近获得了aspect-ratio在 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;
    }
于 2020-05-15T17:27:59.573 回答
9

实际上,高票的答案是一个非常好的解决方案,但是有一个新的 CSS 功能,名称是aspect-ratio.

它可以这样使用:

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

它会自动确定它的高度,但请参阅兼容性表:

在此处输入图像描述

如果浏览器支持对您的项目很重要,请不要使用它。使用该padding-bottom技术。

于 2021-06-02T16:40:40.783 回答
9

您可以使用 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%;" />
于 2016-10-05T05:26:40.183 回答
8

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

当你使用它时,你的 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为高度/宽度,就是这样。

于 2013-12-05T21:13:26.133 回答
8

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

我找到了一些更新鲜的方法来解决这个问题。此解决方案是 anypadding-bottom方法的后代,但没有任何子元素position: absolute,仅使用display: grid;和伪元素。

这里我们有.ratio::before一个很好的旧的padding-bottom: XX%and grid-area: 1 / 1 / 1 / 1;,它强制伪元素保持在网格中的位置。虽然这里我们必须width: 0;防止这个溢出主元素(我们z-index在这里冷使用,但这个更短)。

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

.ratio {
  display: grid;
  grid-template-columns: 1fr;
  max-width: 200px; /* just for instance, can be 100% and depends on parent */  
}

.ratio::before {
  content: '';
  width: 0;
  padding-bottom: calc(100% / (16/9)); /* here you can place any ratio */
  grid-area: 1 / 1 / 1 / 1;
}

.ratio>*:first-child {
  grid-area: 1 / 1 / 1 / 1; /* the same as ::before */
  background: rgba(0, 0, 0, 0.1); /* just for instance */
}
<div class="ratio">
  <div>16/9</div>
</div>


style尽管您可以使用 CSS val 并使用属性将您的比率放在 HTML 中。也适用display: inline-grid

.ratio {
  display: inline-grid;
  grid-template-columns: 1fr;
  width: 200px; /* just for instance, can be 100% and depends on parent */ 
  margin-right: 10px; /* just for instance */
}

.ratio::before {
  content: '';
  width: 0;
  padding-bottom: calc(100% / (var(--r))); /* here you can place any ratio */
  grid-area: 1 / 1 / 1 / 1;
}

.ratio>*:first-child {
  grid-area: 1 / 1 / 1 / 1; /* the same as ::before */
  background: rgba(0, 0, 0, 0.1); /* just for instance */
}
<div class="ratio" style="--r: 4/3;">
  <div>4/3</div>
</div>

<div class="ratio" style="--r: 16/9;">
  <div>16/9</div>
</div>

于 2020-08-03T21:19:27.057 回答
7

这是我的做法:

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

资源

于 2015-10-23T11:18:14.623 回答
7

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

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

于 2017-01-16T13:41:47.640 回答
6

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

@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
} 
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
} 
于 2017-06-16T13:07:16.160 回答
6

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

这取决于一个案例,但在某些情况下它真的很有用。例如 - 您可以在background-image不设置固定高度的情况下进行设置,或者使用它来嵌入<iframe>youtube16:9position:absolute

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

例子:

div{
    background-color:red
}
svg{
    width:100%;
    display:block;
    visibility:hidden
}

.demo-1{width:35%}
.demo-2{width:20%}
<div class="demo-1">
  <svg viewBox="0 0 3 2"></svg>
</div>

<hr>

<div class="demo-2">
  <svg viewBox="0 0 3 2"></svg>
</div>

于 2019-11-08T01:49:40.073 回答
5

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

.wrapper {
  width: 50%;
}

.image-container {
  position: relative;
  width: 100%;
}

.image-container::before {
  content: "";
  display: block;
}

.image-container img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ratio-4-3::before {
  padding-top: 75%;
}

.ratio-3-1::before {
  padding-top: calc(100% / 3);
}

.ratio-2-1::before {
  padding-top: 50%;
}
<div class="wrapper"> <!-- Just to make things a bit smaller -->
  <p>
  Example of an 4:3 aspect ratio, filled by an image with an 1:1 ratio.
  </p>
  <div class="image-container ratio-4-3"> <!-- Lets go for a 4:3 aspect ratio -->
    <img src="https://placekitten.com/1000/1000/" alt="Kittens!" />
  </div>
  <p>
  Just place other block elements around it; it will work just fine.
  </p>
</div>

于 2019-06-02T19:44:25.117 回答
4

使用画布元素保持纵横比的简单方法。

尝试调整下面的 div 大小以查看它的实际效果。

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

.cont {
  border: 5px solid blue;
  position: relative;
  width: 300px;
  padding: 0;
  margin: 5px;
  resize: horizontal;
  overflow: hidden;
}

.ratio {
  width: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

也适用于动态高度!

.cont {
  border: 5px solid blue;
  position: relative;
  height: 170px;
  padding: 0;
  margin: 5px;
  resize: vertical;
  overflow: hidden;
  display: inline-block; /* so the div doesn't automatically expand to max width */
}

.ratio {
  height: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

于 2020-04-17T17:30:44.397 回答
4

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

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

请注意,由于它正在设置元素的高度,因此元素应该是 adisplay:blockdisplay:inline-block

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

于 2017-04-13T21:44:27.983 回答
4

假设您有 2 个 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 */
}

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

于 2016-09-15T02:04:36.077 回答
3

新的宽高比标签会很棒,但它弄乱了我的 div 的定位。填充包装器 div 的传统解决方案有效,但仅根据父级或视口的宽度调整大小,当高度是限制因素时会出现问题

我发现这个min()功能非常有用,并像这样调整了传统方法:

body{
    background-image: linear-gradient(to top right, #FFE6B5, #B3CEBF);
    padding: 0;
    margin: 0 auto;
    overflow-y: hidden; /* this is to avoid scrolling when the height of the viewport is less than what the aspect ratio requires */
}

.wrapper {
    position: relative;
    width: 100vw;
    max-height: 100vh;
}
.sixteen-by-nine.aspect-ratio { 
    padding-bottom: 56.25% /* 9:16 ratio */
}
.content {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
    background-color: green
}

.centered {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    height: 100%;
    width: min(177.8vh, 100%); /* this always keeps a 16:9 ratio within the viewport */
    font-size: min(3vh,1.7vw); /* if you are also interested in scaling the font size */
    background-color: blue
}
<body>
  <div class="wrapper">
    <div class="sixteen-by-nine aspect-ratio"></div>
    <div class="content" >
      <div class="centered">
        <!-- stuff goes here -->
      </div>
    </div>
  </div>
</body>

于 2021-06-21T13:05:50.813 回答
3

只是一个想法或黑客。

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>

于 2015-09-30T15:43:57.030 回答
2

我们是这样解决的:

.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/

于 2021-10-13T16:55:43.843 回答
2

新的 CSSaspect-ratio属性是 Chrome 88 中的新功能,并且很快会在其他浏览器中出现。

aspect-ratio CSS 属性设置框的首选纵横比,将用于计算自动尺寸和其他一些布局功能。

CSS技巧文章

更多信息

div {
  background: rebeccapurple;
  height:100px;
  margin:1em auto;
}

.square {
  aspect-ratio: 1 / 1;
  }
<div class="square">
  
</div>

于 2021-01-20T20:49:28.210 回答
2

假设您喜欢保持 Width: 100px 和 Height: 50px (即 2:1) 只需进行以下数学运算:

.pb-2to1 {
  padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}
于 2018-10-31T10:24:12.680 回答
2

CSS为此提供了一个新属性:aspect-ratio.

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

@supports (aspect-ratio: 1 / 1) {
  div {
    aspect-ratio: 16 / 9;
    background-color: orange;
  }  
}
<div style="width: 200px"></div>
<hr />
<div style="width: 400px"></div>
<hr />
<div style="height: 50px"></div>
<hr />
<div style="height: 10px"></div>

Chrome 和 Edge 自 V88 以来一直完全支持这一点,而 Firefox 自 V81 以来一直在标志后面支持它(设置layout.css.aspect-ratio.enabledabout :config)。true

有关兼容性信息,请查看https://caniuse.com/mdn-css_properties_aspect-ratio

于 2021-04-11T20:51:52.290 回答
1

感谢大家的贡献,我将在此处添加我的解决方案,我主要通过重复接受的答案来产生该解决方案。我喜欢这种方法的主要原因是没有不必要的 DOM,因为我使用:before来做填充的脏活。

@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

于 2021-03-04T08:43:42.763 回答
1

我刚刚创建了一个 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.

于 2020-09-03T12:18:22.833 回答
0

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

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

在此示例中,悬停时添加了 50 像素的顶部和底部边距。

html {
  height: 100%;
}

body {
  margin: 0;
  height: 100%;
}

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}

.fixedRatio {
  max-width: 100vw;
  max-height: calc(9 / 16 * 100vw);
  width: calc(16 / 9 * 100vh);
  height: 100vh;
  
  /* DEBUG */
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: blue;
  font-size: 2rem;
  font-family: 'Arial';
  color: white;
  transition: width 0.5s ease-in-out, height 0.5s ease-in-out; 
}

.fixedRatio:hover {
  width: calc(16 / 9 * (100vh - 100px));
  height: calc(100vh - 100px);
}
<div class='container'>
  <div class='fixedRatio'>
    16:9
  </div>
</div>

JSFiddle 上的演示

于 2020-07-31T10:32:57.147 回答
0

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

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

或使用rem. 但无论如何,他们中的任何一个都应该成功。
rem使用默认字体大小值作为em最接近的字体大小。

于 2021-02-28T00:13:50.183 回答
0

我想分享这个,因为找到一个对我有用的解决方案是一段令人沮丧的日子。我正在使用这些填充技术(上面提到过关于使用填充和绝对定位的一些变化)来为网格/弹性布局内部的类似按钮的元素实现 1:1 的纵横比。布局设置为 100vh 高,以便它始终显示为单个非滚动页面。

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

通常这不是问题,但使用网格时需要注意。网格是 2D 布局,它可以考虑两个轴上的大小和布局。我仍在尝试了解其确切性质,但到目前为止,至少如果您在受两个轴上的 fr 单位约束的网格区域内使用此技术,您几乎肯定会遇到井喷,当方面- ratio 项目增长或以其他方式更改布局(显示:无切换和交换网格区域与 css 也是布局更改问题,导致我的井喷)。

在我的情况下,我限制了不需要的列的高度。将其更改为“自动”而不是“1fr”使我的所有其他布局保持不变并防止井喷,同时仍让我保留漂亮的方形按钮!

我不知道这是否是这里每个人都感到沮丧的根源,但这是一个容易犯的错误,即使使用开发工具也无法让您准确了解井喷的来源在许多情况下,因为它实际上并不是单个元素将其炸毁,而是网格布局自身扩大以保持这些 fr 单位在垂直和水平方向上准确无误。

于 2021-02-05T03:45:17.500 回答
0

在 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());
      }
}
于 2022-02-18T13:47:20.100 回答
0

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

.squares{
  width: 30vw
  height: 30vw

与主要纵横比

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

但是,这是相对于整个视口而言的。因此,如果您需要一个占视口宽度 30% 的 div,则可以改用 30vw,并且由于您知道宽度,因此您可以使用 calc 和 vw 单位在高度中重用它们。

于 2016-01-28T18:04:15.390 回答
-1
container {
   height: 100vh;
   width: 100vw;
}
.container div {
   height: 4em;
   width: 3em;
}
于 2021-05-18T06:58:57.930 回答