只需创建一个带有padding-bottom
百分比值的包装器<div>
,例如:
.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>
这将导致一个高度等于其容器宽度的75%的 <div>
元素 (一个4:3的宽高比)。
这依赖于padding 的工作原理:
百分比是相对于生成的框的包含块的宽度计算的[...] (参考来源:w3.org,强调为本人添加)
其他宽高比和100%宽度的 padding-bottom 值:
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;
}
有几种方法可以指定一个像div这样的元素的固定纵横比,以下是其中的两种:
aspect-ratio
CSS 属性 div {
aspect-ratio: 1 / 1;
width: 50%;
background: teal;
}
<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;
box-sizing: border-box;
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>
vw
单位:您可以使用 vw
单位来设置元素的宽度和高度。这样可以保持元素的纵横比,基于视口宽度。
vw:视口宽度的1/100。[MDN]
或者,您也可以使用 vh
来设置视口高度,甚至使用 vmin
/vmax
来使用视口尺寸中较小/较大的一个(讨论看这里)。
Example: 1:1 aspect ratio
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
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,以及一个创建响应式正方形网格并使其垂直和水平居中的解决方案。
vh / vw单位在IE9+浏览器中受支持。更多信息请参见canIuse。
aspect-ratio
。<div class='demo'></div>
.demo {
background: black;
width: 500px;
aspect-ratio: 4/3;
}
aspect-ratio
的Chromium版本。相反,您可以使用类似于height: calc(100vw * 4 / 3);
的东西。 - Slion在 CSS 实现 aspect-ratio
之前,这个答案就已经写好了。但是今天你应该使用它。
原始答案
我偶然发现了一个我认为是聪明的解决方案,使用<svg>
和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>
的比例设置为您想要的任何值:
<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>
成为一个 替换元素,默认情况下,它位于可变高度的基线上(在 Chrome 中为 4px
,在 Firefox 中为 3.5px
)。基线的高度根据 line-height
而变化,这就是为什么我们需要在伪元素上设置 line-height: 0
来获得准确的比例。更多细节请参见 此处。
<svg>
放置在标记中的版本,因为我可以使用单个类(.ratio
)处理各种比例的容器(而不是为每个可能需要的比例都有一个类)。我找到了一种使用CSS的方法,但是你必须小心,因为它可能会根据你自己网站的流程而改变。我这样做是为了在我的网站中将具有恒定纵横比的视频嵌入到流动宽度部分中。
假设你有一个类似于以下嵌入式视频:
<object>
<param ... /><param ... />...
<embed src="..." ...</embed>
</object>
您可以将此所有内容放入具有“video”类的div中。该视频类可能是您网站中的流体元素,因此它本身没有直接的高度限制,但是当您调整浏览器大小时,它会根据网站的流动而改变其宽度。这可能是您尝试嵌入视频并同时保持特定纵横比的元素。<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%来充分利用动态图像提供的可用空间。
相当不错,是吧?
您可能需要根据自己的设计进行一些尝试才能使其正常工作,但对我来说,这实际上效果出奇的好。 总体概念已经在这里了。
Elliot启发了我这个解决方案 - 谢谢:
aspectratio.png
是一个完全透明的PNG文件,大小为您喜欢的宽高比,例如我的情况是30x10像素。
<div class="eyecatcher">
<img src="/img/aspectratio.png"/>
</div>
.eyecatcher img {
width: 100%;
background-repeat: no-repeat;
background-size: 100% 100%;
background-image: url(../img/autoresized-picture.jpg);
}
请注意:background-size
是一个 CSS3 的特性,可能无法在目标浏览器中正常工作。您可以检查互操作性(例如在caniuse.com上)。
正如 @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
。如果您想先确保高度,则应该交换宽度和高度,例如,在9:16肖像模式下使用height:100vh;width: calc(100vh * 9 / 16)
。
如果您希望适应不同的屏幕尺寸,您可能会对以下内容感兴趣:
@media (orientation: portrait)
/@media (orientation: landscape)
正如在 w3schools.com 上所述,并在这个被接受的答案中有所强调,使用百分比值的 padding 值 (重点在我):
指定包含元素宽度的百分比填充
因此,保持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>
<div>
元素的高度(完全由底部填充区域组成)将是其包含元素宽度的75%。这是一个很好的总结:http://mattsnider.com/css-using-percent-for-margin-and-padding/。我不确定为什么会这样,但事实就是如此。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请求。
使用 CSS 的 aspect-ratio
属性。
https://caniuse.com/#search=aspect-ratio
如果您想了解如何使用它,请查看下面超级简单的示例。
.yourClass {
aspect-ratio: 4/3;
}