更改高度时保持图像宽高比


114

使用CSS flex box模型,如何强制图像保持其纵横比?

JS小提琴:http//jsfiddle.net/xLc2Le0k/2/

请注意,图像会拉伸或收缩以填充容器的宽度。很好,但是我们还可以拉伸或缩小高度以保持图像比例吗?

的HTML

<div class="slider">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
</div>

的CSS

.slider {
    display: flex;
}
.slider img {
    margin: 0 5px;
}

1
据我所知,最好的解决方案是<div>与CSS 一起使用background-image: url(...);background-size:contain; background-repeat:no-repeat
Blazemonger,2015年

1
这里有一些有趣的线索,但是当图像的比例不一样时该怎么办?添加和“额外” div是我们需要担心的最后一件事。为什么不使用测试用例是这样,而不是: jsfiddle.net/sheriffderek/999Lg9qv
sheriffderek

Answers:


67

对于img标签,如果您定义一侧,那么将调整另一侧的大小以保持宽高比,并且默认情况下,图像会扩展到其原始大小。

使用这个事实,如果将每个img标签包装到div标签中,并将其宽度设置为父div的100%,则高度将根据所需的纵横比确定。

http://jsfiddle.net/0o5tpbxg/

* {
    margin: 0;
    padding: 0;
}
.slider {
    display: flex;
}
.slider .slide img {
    width: 100%;
}

2
我知道建议使用divs有两个答案,但是我将此答案标记为正确,因为它解释了为什么图像高度与我预期的不同。实际上,这是正常且正确的行为,不太可能被“修复”,因为它不是错误。
coderMe 2015年

18
但是这个答案没有涉及到flexbox,因为在flexbox容器中图像的行为确实有所不同。设置一侧不会按比例调整另一侧的大小。将它们包装在非flexbox容器中会有所帮助,但这会增加不必要的标记,从而失去语义。
罗伯特·科里特尼克'16

3
看起来您不需要包装div才能完成此工作:jsfiddle.net/xLc2Le0k/120
Rick Strahl

4
但是,那呢?jsfiddle.net/xLc2Le0k/15 我认为这种解决方案是a 幸的,因为图像的比例都相同,所以它只能起作用。旁注:通过将图像放置在div中进行定位,尤其是在处理响应图像时,不会丢失任何“语义”。
sheriffderek

1
认真最干净的解决方案,它与图片一起使用!
shaneonabike

64

为了防止图像在弹性父级中沿任一轴拉伸,我找到了两种解决方案。

您可以尝试在图像上使用对象拟合,例如

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

或者,您可以添加特定于弹性的规则,在某些情况下可能会更好。

align-self: center;
flex: 0 0 auto;

4
对象匹配可能是一个很好的解决方案,如果它在IE和Edge中缺少支持,甚至不超过Edge 14
daniels'July


我自己一直在使用该后备,效果很好。
马蒂·巴兰


1
object-fit: contain;当我只遇到铬的问题时,ff帮了我大忙。
本杰明·彼得

53

无需添加包含div。

CSS的“ align-items”属性的默认值为“ stretch”,这是导致图像被拉伸到其原始高度的原因。将css的“ align-items”属性设置为“ flex-start”可解决您的问题。

.slider {
    display: flex;
    align-items: flex-start;  /* ADD THIS! */
}

3
啊...感谢您以支持的方式进行操作。我正在读答案,直到那一个,简直不敢相信我们所做的是肮脏的黑客..
费利克斯·加侬-格尼尔

35

大多数具有固有尺寸的图像,即自然尺寸,如jpeg图像。如果指定的尺寸同时定义了宽度和高度之一,则使用固有比率确定缺失值...-参见MDN

但是,据我所知,如果使用当前“ 灵活框布局模块级别1”将图像设置为直接柔版项目,则无法正常工作。

请参阅以下讨论和错误报告可能相关:


解决方法是,您可以<img>使用<div>或包裹每个包裹<span>

jsFiddle

.slider {
  display: flex;
}

.slider>div {
  min-width: 0; /* why? see below. */
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

4.5弹性项目的隐含最小大小

为了为弹性商品提供更合理的默认最小尺寸,该规范引入了一个新的自动值作为CSS 2.1中定义的min-widthmin-height属性的初始值。


另外,您也可以使用CSS table布局,它将获得与相似的结果flexbox,即使在IE8上,它也可以在更多浏览器上使用。

jsFiddle

.slider {
  display: table;
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.slider>div {
  display: table-cell;
  vertical-align: top;
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>


.slider > div{min-width:0}支持的新浏览器需要第一个片段min-width: auto
Oriol 2015年

3
该Flexbox将规范引入了一个新auto的值作为默认值min-widthmin-height(以前是0)。Chrome尚未实现,因此您的第一个代码段可以使用。但是新的浏览器需要它,以允许弹性项目缩小到小于图像的默认宽度。
Oriol

2
+1这个应该被接受的答案,因为它谈论的是flexbox模型中的图像,这是本例中的根本问题 ……
Robert Koritnik

如果您的布局在各个断点处都没有变化,那么表就很棒,但是现在这不太可能。
sheriffderek

1
如果图像的比例不一样怎么办? jsfiddle.net/sheriffderek/5u7y21we
sheriffderek

6

我最近一直在flexbox周围玩耍,我通过实验和以下推理得出了解决方案。但是,实际上我不确定这是否会发生。

如果实际宽度受柔韧性系统影响。因此,在元素的宽度达到父元素的最大宽度之后,它们在CSS中设置的额外宽度将被忽略。然后将宽度设置为100%是安全的。

由于img标签的高度来自图像本身,因此将高度设置为0%可能会有所作为。(这是我不清楚的地方...但是对我来说应该修复它)

演示

(记住首先在这里看到它!)

.slider {
    display: flex;
}
.slider img {
    height: 0%;
    width: 100%;
    margin: 0 5px;
}

仅适用于Chrome


有趣,但似乎是一个错误。根据规范,“ 百分比是根据生成的框的包含块的高度计算的。如果未明确指定包含块的高度(即,它取决于内容的高度),并且此元素未绝对定位,该值计算为auto “。这就是在Firefox上发生的事情。
Oriol 2015年

jsfiddle.net/xLc2Le0k/8解释了ff和chrome的区别。为此
Muhammad Umer

ff的宽度似乎与chrome的高度相同。
Muhammad Umer

这很有趣,但是恐怕纯X浏览器的解决方案并不是真正的解决方案。您在这里评论过的小提琴:jsfiddle.net/xLc2Le0k/8在FF中绝对令人着迷。这似乎表明FF使图像的高度与图像的高度“成比例”(如果它确实为100%)。换句话说,img不会“知道”容器的显示:flex。这解释了为什么在FF中,如果将img的宽度设置为100%,则图像比将宽度设置为auto时要高。
coderMe 2015年

这是有点接近......但只有在Chrome的工作: jsfiddle.net/sheriffderek/xLc2Le0k/270
sheriffderek

2

此行为是预期的。默认情况下,flex容器将拉伸其所有子级。图片也不例外。(即,父母将拥有align-items: stretch财产)

为了保持长宽比,我们有两种解决方案:

  1. 将默认align-items: stretch属性替换为align-items: flex-startalign-self: center等等, http://jsfiddle.net/e394Lqnt/3/

要么

  1. 设置align属性专门为孩子本身:喜欢,align-self: center或者align-self: flex-starthttp://jsfiddle.net/e394Lqnt/2/

-1

实际上,我发现图像标签的容器需要具有一定的高度才能保持图像的比例。例如>

.container{display:flex; height:100%;} img{width:100%;height:auto;}

然后在您的html中,您的容器将包装标签图像

<div class="container"><img src="image.jpg" alt="image" /></div>

这项功能适用于IE和其他浏览器


-1

我只是有同样的问题。使用flex align将元素居中。您需要使用align-items: center而不是align-content: center。这将保持纵横比,而对齐内容将不会保持纵横比。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.