在 Flexbox 中居中和缩放图像

Posted

技术标签:

【中文标题】在 Flexbox 中居中和缩放图像【英文标题】:Centering and Scaling an Image in a Flexbox 【发布时间】:2015-10-05 19:47:58 【问题描述】:

如果容器内的 am <img>(尺寸未知)设置为display:flexbox,是否可以满足以下条件:

    如果图像的原生宽度小于容器的宽度,则它在容器内水平居中。

    如果图像的原生高度小于容器的高度,则它与容器垂直居中。

    如果图像的原生宽度大于容器的宽度,则图像将缩放到容器的宽度。

    如果图像的原生高度大于容器的高度,则图像将缩放到容器的高度。

我注意到 Chrome 和 Firefox 处理 flexbox 子图像的方式存在很大差异。 Chrome 到达一半,但垂直挤压图像。 Firefox 到了一半,但水平挤压图像:Codepen

body,
html 
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;


.Container 
  height: 100%;
  width: 100%;
  background: red;
  display: flex;
  justify-content: center;
  align-items: center;


img
  max-height: 100%;
  max-width: 100%;
<div class="Container">
    <img src="http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487">
</div>

这是我能得到的最接近的Codepen,它在 4 上失败了。:

body,
html 
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;


.Container 
  height: 100%;
  width: 100%;
  background: red;
  display: flex;
  justify-content: center;
  align-items: center;


.ImageWrapper 
  max-height: 100%;
  max-width: 100%;


img
  max-height: 100%;
  max-width: 100%;
  width: 100%;
  height: auto;
<div class="Container">
  <div class="ImageWrapper">
    <img src="http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487">
  </div>
</div>

我知道这种行为以前如果没有 javascript 是不可能的,但我很惊讶使用 flexbox 似乎无法实现。

注意:我不是在寻找 JavaScript 解决方案或在现代浏览器中无法运行的解决方案。

针对 David Mann 的回答,这里是前面使用 object-fit Codepen 的示例。

body,
html 
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;


.Container 
  height: 100%;
  width: 100%;
  background: red;
  display: flex;
  justify-content: center;
  align-items: center;


img
  max-height: 100%;
  max-width: 100%;
  object-fit: contain;
<div class="Container">
    <img src="http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487">
</div>

这是使用polyfill 的Codepen。在 IE10 中似乎可以正常工作,但在 IE11 中出现故障。

【问题讨论】:

我认为您的演示运行良好(在 Chrome 中测试),我认为问题是,图像不会在屏幕调整大小时按比例缩放(宽度在 Chrome 中没有按比例增长)但是当您调整窗口大小然后让页面重新加载,它可以很好地缩放。调整窗口大小时,你真的需要它来缩放吗? @KiiroSora09 不幸的是,Firefox 并非如此,即使在页面重新加载时也会挤压图像。 抱歉,我现在没有 Firefox。也许您可以将 flex 与 object-fit 结合起来(来自下面大卫的回答)。因此对象适合将在现代浏览器上运行,并在 IE 11 上回退到 flex。 @KiiroSora09 是的。我认为这可能是要走的路。 除了我suggested在@Pedr下面的其他方法之外,您可以将容器设置为flex-direction: column; works 在 Chrome 上很好,但在 Firefox 上不太好(当您使视口短于图像的固有高度,纵横比发生变化)。我已经多次看到类似的问题 - 关于将图像设置为直接弹性项目的问题,但是,仍然没有很好的答案,这个 answer 是我见过的最接近的,希望它有所帮助。 【参考方案1】:

CSS 正在迎头赶上。它还没有最大的support,但object-fit: contain 完全符合您的要求(编辑 11/17:Edge 现在有部分支持,使 IE11 成为唯一不支持的浏览器)。只需将其放入 img 的 css 规则中,然后将 max-width: 100%max-height: 100% 更改为 width: 100%height: 100%。这是codepen。

.Container 
  height: 100vh;
  width: 100vw;
  background: red;
  display: flex;
  justify-content: center;
  align-items: center;


img 
  height: 100%;
  width: 100%;
  object-fit: contain;


body 
  margin: 0;
<div class="Container">
  <img src="https://unsplash.it/2000/1500">
</div>

如果 IE 缺乏对 object-fit 的支持是一个交易破坏者,那么有一个 javascript polyfill 支持它。以下是来自css-tricks 的更多信息。

background-image 也可以达到同样的效果,但感觉有点作弊。

只需将此添加到.Container

background-image: url(http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487);
background-size: contain;
background-repeat:no-repeat;
background-position: center;

然后完全删除img标签。效果是一样的,但.Container 中没有实际元素。需要注意的是,使用这种方法display: flex 甚至不需要。

这是此方法的另一个 codepen。

.Container 
  height: 100vh;
  width: 100vw;
  background: red;
  background-image: url(https://unsplash.it/2000/1500);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;


body 
  margin: 0;
<div class="Container">
</div>

这里的support 好多了,还有更多可以玩的东西。再一次,这是来自 css-tricks 的 almanac entry

【讨论】:

哇!我不知道这样的事情存在!我希望我们尽快得到更好的支持。 谢谢。我什至不知道这一点,但它目前还不能使用。 polyfill doesn't even work in IE11. 我在问题中添加了一个使用object-fit 的示例。 哇,我还没有看到 IE11 的这个问题。我正在考虑将 polyfill 用于我正在从事的项目。很高兴我找到了一个可接受的解决方法,而不是使用它。遗憾的是它不涉及 IE 的object-fit,否则我会在这里发布。 刚刚在 IE10 和 IE11 中测试过,似乎工作正常:codepen.io/anon/pen/VLBwVG【参考方案2】:

方法一:使用 CSS 表格单元格,请看以下演示。

div 
    border: 1px solid red;
    width: 100px;
    height: 100px;
    display: table-cell;
    text-align: center;
    vertical-align: middle;

img 
    max-width: 100%;
    max-height: 100%;
    vertical-align: middle;
<div><img src="//dummyimage.com/75x50" /></div>
<div><img src="//dummyimage.com/50x75" /></div>
<div><img src="//dummyimage.com/300x200" /></div>
<div><img src="//dummyimage.com/200x300" /></div>
<div><img src="//dummyimage.com/200x200" /></div>

方法 2: 使用内联块,请参阅下面的注释。

div 
    border: 1px solid red;
    width: 100px;
    height: 100px;
    display: inline-block;
    text-align: center;
    vertical-align: top;

div:before 
    content: "";
    height: 100%;
    display: inline-block;
    vertical-align: middle;

img 
    max-width: 100%;
    max-height: 100%;
    vertical-align: middle;
<div><img src="//dummyimage.com/75x50" /></div>
<div><img src="//dummyimage.com/50x75" /></div>
<div><img src="//dummyimage.com/300x200" /></div>
<div><img src="//dummyimage.com/200x300" /></div>
<div><img src="//dummyimage.com/200x200" /></div>

补充说明:在父容器内有空的时候设置font-size:0;,如果里面有文字内容,再在容器内重置为font-size:16px;左右。关注此以获取更多信息 - https://***.com/a/5078297/483779

【讨论】:

以上是关于在 Flexbox 中居中和缩放图像的主要内容,如果未能解决你的问题,请参考以下文章

将图像缩放到 flexbox 中的最大尺寸 [重复]

CSS:Firefox/Internet Explorer 中 flexbox 的图像缩放问题

如何在 flexbox 中居中文本?

在 Flexbox 中居中不起作用。啥是高度、宽度、显示和位置要求?我错过了啥? [复制]

Flexbox 使用原始 SVG 宽度而不是缩放宽度

在 IE11 上的嵌套 flexbox 容器中保持图像纵横比