Html 使用 CSS 保持 div 的纵横比
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1495407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Maintain the aspect ratio of a div with CSS
提问by Hymanb
I want to create a div
that can change its width/height as the window's width changes.
我想创建一个div
可以随着窗口宽度的变化而改变其宽度/高度的。
Are there any CSS3 rules that would allow the height to change according to the width, while maintaining its aspect ratio?
是否有任何 CSS3 规则允许高度根据宽度改变,同时保持其纵横比?
I know I can do this via JavaScript, but I would prefer using only CSS.
我知道我可以通过 JavaScript 做到这一点,但我更喜欢只使用 CSS。
回答by Web_Designer
Just create a wrapper <div>
with a percentage value for padding-bottom
, like this:
只需创建一个<div>
带有百分比值的包装器padding-bottom
,如下所示:
div {
width: 100%;
padding-bottom: 75%;
background: gold; /** <-- For the demo **/
}
/* demonstration purposed only : non-essential */
.demoWrapper {
padding: 10px;
background: white;
box-sizing: border-box;
resize: horizontal;
border: 1px dashed;
overflow: auto;
max-width: 100%;
height: calc(100vh - 16px);
}
<div class="demoWrapper">
<div></div>
</div>
It will result in a <div>
with height equal to 75% of the width of its container (a 4:3 aspect ratio).
这将导致<div>
高度等于其容器宽度的 75%(4:3 纵横比)。
This relies on the fact that for padding :
这取决于填充的事实:
The percentage is calculated with respect to the widthof the generated box's containing block [...] (source: w3.org, emphasis mine)
百分比是根据生成的框的包含块 [...]的宽度计算的(来源:w3.org,重点是我的)
Padding-bottom values for other aspect ratios and 100% width :
其他宽高比和 100% 宽度的 Padding-bottom 值:
aspect ratio | padding-bottom value
--------------|----------------------
16:9 | 56.25%
4:3 | 75%
3:2 | 66.66%
8:5 | 62.5%
Placing content in the div :
在 div 中放置内容:
In order to keep the aspect ratio of the div and prevent its content from stretching it, you need to add an absolutely positioned child and stretch it to the edges of the wrapper with:
为了保持 div 的纵横比并防止其内容拉伸它,您需要添加一个绝对定位的子项并将其拉伸到包装器的边缘:
div.stretchy-wrapper {
position: relative;
}
div.stretchy-wrapper > div {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
}
Here's a demoand another more in depth demo
回答by web-tiki
vw
units:
vw
单位:
You can use vw
units for both the width and heightof the element. This allows the element's aspect ratio to be preserved, based on the viewport width.
您可以对元素vw
的宽度和高度使用单位。这允许根据视口宽度保留元素的纵横比。
vw : 1/100th of the width of the viewport. [MDN]
vw :视口宽度的 1/100。[ MDN]
Alternatively, you can also use vh
for viewport height, or even vmin
/vmax
to use the lesser/greater of the viewport dimensions (discussion here).
或者,您也可以使用vh
视口高度,甚至vmin
/vmax
来使用较小/较大的视口尺寸(此处讨论)。
Example: 1:1 aspect ratio
示例:1:1 纵横比
div {
width: 20vw;
height: 20vw;
background: gold;
}
<div></div>
For other aspect ratios, you can use the following table to calculate the value for height according to the width of the element :
对于其他长宽比,您可以使用下表根据元素的宽度计算高度的值:
aspect ratio | multiply width by
-----------------------------------
1:1 | 1
1:3 | 3
4:3 | 0.75
16:9 | 0.5625
Example: 4x4 grid of square divs
示例:方形 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 demoand here is a solution to make a responsive grid of squares with verticaly and horizontaly centered content.
Here is a Fiddle with this demoand here is a solution to make a response grid of squares with verticaly and水平居中的内容。
Browser support for vh/vw units is IE9+ see canIuse for more info
浏览器对 vh/vw 单位的支持是 IE9+,请参阅canIuse 了解更多信息
回答by forgo
I've found a way to do this using CSS, but you have to be careful as it may change depending on the flow of your own web site. I've done it in order to embed video with a constant aspect ratio within a fluid width portion of my web site.
我已经找到了一种使用 CSS 来做到这一点的方法,但您必须小心,因为它可能会根据您自己网站的流程而改变。我这样做是为了在我网站的流体宽度部分中嵌入具有恒定纵横比的视频。
Say you have an embedded video like this:
假设您有一个这样的嵌入式视频:
<object>
<param ... /><param ... />...
<embed src="..." ...</embed>
</object>
You could then place this all inside a div with a "video" class. This video class will probably be the fluid element in your website such that, by itself, it has no direct height constraints, but when you resize the browser it will change in width according to the flow of the web site. This would be the element you are probably trying to get your embedded video in while maintaining a certain aspect ratio of the video.
然后,您可以将所有这些都放在带有“视频”类的 div 中。这个视频类可能是您网站中的流体元素,因此它本身没有直接的高度限制,但是当您调整浏览器的大小时,它会根据网站的流量改变宽度。这将是您可能试图在保持视频的特定纵横比的同时获得嵌入视频的元素。
In order to do this, I put an image before the embedded object within the "video" class div.
为了做到这一点,我在“视频”类 div 中的嵌入对象之前放置了一个图像。
!!! The important part is that the image has the correct aspect ratio you wish to maintain. Also, make sure the size of the image is AT LEAST as big as the smallest you expect the video (or whatever you are maintaining the A.R. of) to get based on your layout. This will avoid any potential issues in the resolution of the image when it is percentage-resized. For example, if you wanted to maintain an aspect ratio of 3:2, don't just use a 3px by 2px image. It may work under some circumstances, but I haven't tested it, and it would probably be a good idea to avoid.
!!!重要的部分是图像具有您希望保持的正确纵横比。此外,请确保图像的大小至少与您期望视频(或您维护 AR 的任何内容)根据您的布局获得的最小尺寸一样大。这将避免图像按百分比调整大小时出现任何潜在的分辨率问题。例如,如果您想保持 3:2 的纵横比,不要只使用 3px x 2px 的图像。在某些情况下它可能会起作用,但我尚未对其进行测试,因此避免使用它可能是一个好主意。
You should probably already have a minimum width like this defined for fluid elements of your web site. If not, it is a good idea to do so in order to avoid chopping elements off or having overlap when the browser window gets too small. It is better to have a scroll bar at some point. The smallest in width a web page should get is somewhere around ~600px (including any fixed width columns) because screen resolutions don't come smaller unless you are dealing with phone-friendly sites. !!!
您可能已经为网站的流体元素定义了这样的最小宽度。如果没有,这样做是个好主意,以避免在浏览器窗口太小时切掉元素或重叠。在某些时候最好有一个滚动条。网页应该获得的最小宽度约为 600 像素(包括任何固定宽度的列),因为除非您处理的是适合手机的网站,否则屏幕分辨率不会变小。!!!
I use a completely transparent png but I don't really think it ends up mattering if you do it right. Like this:
我使用完全透明的 png,但我真的认为如果你做得对,它最终并不重要。像这样:
<div class="video">
<img class="maintainaspectratio" src="maintainaspectratio.png" />
<object>
<param ... /><param ... />...
<embed src="..." ...</embed>
</object>
</div>
Now you should be able to add CSS similar to the following:
现在您应该能够添加类似于以下内容的 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%; }
Make sure you also remove any explicit height or width declaration within the object and embed tags that usually come with copy/pasted embed code.
确保您还删除了对象中的任何明确的高度或宽度声明,并嵌入通常随复制/粘贴嵌入代码一起提供的标签。
The way it works depends on the position properties of the video class element and the item you want have maintain a certain aspect ratio. It takes advantage of the way an image will maintain its proper aspect ratio when resized in an element. It tells whatever else is in video class element to take full-advantage of the real estate provided by the dynamic image by forcing its width/height to 100% of the video class element being adjusted by the image.
它的工作方式取决于视频类元素的位置属性以及您希望保持一定纵横比的项目。它利用了图像在元素中调整大小时保持其适当纵横比的方式。它告诉视频类元素中的任何其他内容,通过将动态图像的宽度/高度强制为由图像调整的视频类元素的 100%,从而充分利用动态图像提供的空间。
Pretty cool, eh?
很酷吧?
You might have to play around with it a bit to get it to work with your own design, but this actually works surprisingly well for me. The general concept is there.
你可能需要稍微尝试一下才能让它与你自己的设计一起工作,但这对我来说实际上效果非常好。一般概念就在那里。
回答by Florian Breisch
Elliot inspired me to this solution - thanks:
Elliot 启发了我这个解决方案 - 谢谢:
aspectratio.png
is a completely transparent PNG-file with the size of your preferred aspect-ratio, in my case 30x10 pixels.
aspectratio.png
是一个完全透明的 PNG 文件,大小为您首选的纵横比,在我的情况下为 30x10 像素。
HTML
HTML
<div class="eyecatcher">
<img src="/img/aspectratio.png"/>
</div>
CSS3
CSS3
.eyecatcher img {
width: 100%;
background-repeat: no-repeat;
background-size: 100% 100%;
background-image: url(../img/autoresized-picture.jpg);
}
Please note:background-size
is a css3-feature which might not work with your target-browsers. You may check interoperability (f.e. on caniuse.com).
请注意:background-size
是 css3 功能,可能不适用于您的目标浏览器。您可以检查互操作性(fe on caniuse.com)。
回答by nabrown
To add to Web_Designer's answer, the <div>
will have a height (entirely made up of bottom padding) of 75% of the width of it's containing element. Here's a good summary: http://mattsnider.com/css-using-percent-for-margin-and-padding/. I'm not sure why this should be so, but that's how it is.
要添加到 Web_Designer 的答案中,它<div>
的高度(完全由底部填充组成)为其包含元素的宽度的 75% 。这是一个很好的总结:http: //mattsnider.com/css-using-percent-for-margin-and-padding/。我不确定为什么会这样,但事实就是这样。
If you want your div to be a width other than 100%, you need another wrapping div on which to set the width:
如果您希望 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;
}
I used something similar to Elliot's image trick recently to allow me to use CSS media queries to serve a different logo file depending on device resolution, but still scale proportionally as an <img>
would naturally do (I set the logo as background image to a transparent .png with the correct aspect ratio). But Web_Designer's solution would save me an http request.
我最近使用了类似于 Elliot 的图像技巧的东西,允许我使用 CSS 媒体查询来根据设备分辨率提供不同的徽标文件,但仍然按比例缩放<img>
(我将徽标设置为背景图像为透明的 .png具有正确的纵横比)。但是 Web_Designer 的解决方案将为我节省一个 http 请求。
回答by Marc A
As stated in here on w3schools.comand somewhat reiterated in this accepted answer, padding values as percentages (emphasis mine):
正如在 w3schools.com 上所述,并在此接受的答案中有所重申,将值填充为百分比(强调我的):
Specifies the padding in percent of the width of the containing element
以包含元素宽度的百分比指定填充
Ergo, a correct example of a responsive DIV that keeps a 16:9 aspect ratio is as follows:
因此,保持 16:9 纵横比的响应式 DIV 的正确示例如下:
CSS
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
HTML
<div class="parent">
<div class="child">
<div>Aspect is kept when resizing</div>
</div>
</div>
回答by wener
As @web-tiki already show a way to use vh
/vw
, I also need a way to center in the screen, here is a snippet code for 9:16portrait.
由于@web-tiki 已经展示了一种使用vh
/ 的方法vw
,我还需要一种将屏幕居中的方法,这里是9:16肖像的片段代码。
.container {
width: 100vw;
height: calc(100vw * 16 / 9);
transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}
translateY
will keep this center in the screen. calc(100vw * 16 / 9)
is expected height for 9/16.(100vw * 16 / 9 - 100vh)
is overflow height, so, pull up overflow height/2
will keep it center on screen.
translateY
将保持这个中心在屏幕上。calc(100vw * 16 / 9)
是 9/16 的预期高度。(100vw * 16 / 9 - 100vh)
是溢出高度,因此,上拉overflow height/2
将使其保持在屏幕中心。
For landscape, and keep 16:9, you show use
对于风景,并保持16:9,您显示使用
.container {
width: 100vw;
height: calc(100vw * 9 / 16);
transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}
The ratio 9/16 is ease to change, no need to predefined 100:56.25
or 100:75
.If you want to ensure height first, you should switch width and height, e.g. height:100vh;width: calc(100vh * 9 / 16)
for 9:16 portrait.
9/16的比例很容易改变,不需要预定义100:56.25
或100:75
。如果你想先确保高度,你应该切换宽度和高度,例如height:100vh;width: calc(100vh * 9 / 16)
9:16纵向。
If you want to adapted for different screen size, you may also interest
如果你想适应不同的屏幕尺寸,你可能还感兴趣
- background-sizecover/contain
- Above style is similar to contain, depends on width:height ratio.
- object-fit
- cover/contain for img/video tag
@media (orientation: portrait)
/@media (orientation: landscape)
- Media query for
portrait
/landscape
to change the ratio.
- Media query for
回答by Salman A
This is an improvement on the accepted answer:
这是对已接受答案的改进:
- Uses pseudo elements instead of wrapper divs
- The aspect ratio is based on the width of the box instead of its parent
- The box will stretch vertically when the content becomes taller
- 使用伪元素而不是包装 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>
回答by tao
I stumbled upon a smart solutionusing <svg>
and display:grid
.
我偶然发现了一个使用<svg>
和的智能解决方案display:grid
。
Grid element allows you to occupy the same space with two (or more) elements, without needing to specify which one sets the height. Which means that, out of the box, the taller one sets the ratio.
网格元素允许您用两个(或多个)元素占据相同的空间,而无需指定哪一个设置高度。这意味着,开箱即用,较高的设置比率。
This means you can use it as is when you know the content will never be tall enough to fill the entire "ratio" and you're simply looking for a way to position the content in this space (i.e. to center it on both directions use
display:flex; align-items:center; justify-content:center
).
It's pretty much the same as using a transparent <img>
with display:block
and predetermined ratio, except the <svg>
is lighter and considerably easier to modify (to change the ratio responsively, should you need to).
这意味着您可以按原样使用它,当您知道内容永远不会高到足以填充整个“比例”并且您只是在寻找一种将内容定位在此空间中的方法(即使其在两个方向上居中时使用
display:flex; align-items:center; justify-content:center
)。
这几乎是一样采用了透明<img>
带display:block
和预定的比例,除了<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/1/1;
}
All you need to do is change the <svg>
s ratio:
您需要做的就是更改<svg>
s 比率:
<svg viewBox="0 0 4 3"></svg>
<svg viewBox="0 0 16 9"></svg>
<svg viewBox="0 0 4 3"></svg>
<svg viewBox="0 0 16 9"></svg>
See it working:
看到它工作:
.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;
}
<div class="ratio">
<svg viewBox="0 0 7 1"></svg>
<div>
Fixed ratio 7:1
</div>
</div>
If you need a solution where the content element is not allowed to set the ratio when it's taller (with overflow hidden or auto), you need to set position:relative
on the grid and position:absolute; height:100%; overflow-y: auto;
on the content. Example:
如果您需要一个解决方案,内容元素在较高时不允许设置比例(溢出隐藏或自动),则需要position:relative
在网格和position:absolute; height:100%; overflow-y: auto;
内容上进行设置。例子:
.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;
}
<div class="ratio">
<svg viewBox="0 0 7 1"></svg>
<div>
<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>
回答by pie6k
Basing on your solutions I've made some trick:
根据您的解决方案,我做了一些技巧:
When you use it, your HTML will be only
当您使用它时,您的 HTML 将仅
<div data-keep-ratio="75%">
<div>Main content</div>
</div>
To use it this way make: CSS:
以这种方式使用它:CSS:
*[data-keep-ratio] {
display: block;
width: 100%;
position: relative;
}
*[data-keep-ratio] > * {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
and js (jQuery)
和 js (jQuery)
$('*[data-keep-ratio]').each(function(){
var ratio = $(this).data('keep-ratio');
$(this).css('padding-bottom', ratio);
});
And having this you just set attr data-keep-ratio
to height/width and that's it.
有了这个,您只需将 attr 设置data-keep-ratio
为高度/宽度即可。