flex 布局下 img 显示问题

常规的 Flex 布局实例如下:

<div class="div-ctn">
  <div class="first-div">第一个 div</div>
  <div class="second-div">第二个 div</div>
</div>
1
2
3
4
.div-ctn {
  display: flex;
}
.div-ctn > div {
  flex-grow: 1;
}
.div-ctn  > .first-div {
  background: red;
}
.div-ctn  > .second-div {
  background: blue;
}
1
2
3
4
5
6
7
8
9
10
11
12

结果:

flex 布局常规示例

问题

但是将上例里的div-ctn里的div元素替换成img元素,就会出现问题。

这里有两张图片,一张是600*600像素的图片,另一张是2000*3000像素的图片。

Vue logoCar

<div class="img-ctn">
  <img src="https://windstone.cc/hero.png">
  <img src="https://windstone.cc/car.png">
</div>
1
2
3
4
.img-ctn {
  display: flex;
}
.img-ctn > img {
  flex: auto;
}
1
2
3
4
5
6

结果:

图片异常

我们期望的是,在屏幕范围内并排显示两张完整的图片,并保持着原始比例。

而实际上,图片却按原始的600*600的尺寸来显示,导致出现了横向的滚动条。

解决方案

针对img元素等替换元素来说,在作为 Flex 容器的子元素时,需要确定宽度或者高度,才能按期望进行放大和缩小。

确定宽度

我们先给img象征性地添加width: 1px,而flex: auto可以确保子元素等比例放大以充满剩余空间。

.img-ctn {
  display: flex;
}
.img-ctn > img {
  flex: auto;
  width: 1px;
}
1
2
3
4
5
6
7

结果是,图片按期望的在屏幕内并排显示,但是却没有保持图片原来的比例。

stretch 的图片

align-items

上例里的图片没有成比例显示而是拉伸,是因为 Flex 容器的align-items默认值是stretch,即子元素在交叉轴上将占满整个容器的高度(子元素未设置高度或高度设为auto时)。而且第二张图片高为2000px,导致容器的高度也撑到了2000px,导致两张图片未保持原始的宽高比,出现了严重的拉伸效果。

想要消除这种拉伸效果,可以设置容器的align-items(或者子元素的align-self)为flex-start,即可让图片保持原始比例。

正常的图片

确定高度

确定图片的高度,也能解决图片拉伸的问题。但是一般情况下,我们都会要求保持图片的宽高比,而当图片高度确定后,图片宽度可能会随着容器的扩大而扩大、缩小而缩小,导致不能维持宽高比。因此,一般不会采用确定高度的方式。