为什么 flexbox 项目图像会根据其初始大小调整不同的大小?

Why do flexbox item images resize differently according to their initial size?

我有四张图片:两张小的,两张大的(html中显示的尺寸)。它们的 img 宽度都设置为 100%,但它们的父 div 设置为特定宽度。当我调整浏览器大小时 window 较小的图像会立即缩小而较大的图像不会立即缩小。

我在 div 周围有红色边框,在 img 周围有绿色边框。较小图像的绿色边框先于较大图像缩小。这是为什么?

http://jsfiddle.net/brcrnj80/6/

img {
  border: 3px solid green;
  width: 100%;
}

.item {
  border: 1px solid red;
  max-width: 250px;
  min-width: 60px;
  margin: 10px;
}

谢谢

tl;dr:项目调整大小不同,因为它们具有不同的 flex-basis,这是基于图像大小并且是它们开始弯曲(收缩)的值。每个项目都要缩小,但较大的项目从较大的起点收缩,所以缩小后它们仍然较大。 (还有一个后期算法 "clamp" 来防止它们比它们的 max-width 大;这就是在这种情况下防止大项目变得疯狂巨大的原因。但重要的是,它们从他们的 flex-basis 开始收缩 max-width 限制是事后才想到的。)

FIX: 如果你给每个弹性项目相同的弹性基础,例如flex-basis:250px(与他们的 max-width 相同),您可能会得到想要的结果。更新 fiddle:http://jsfiddle.net/brcrnj80/10/

(如另一个答案所述,flex: 1 1 0(可以更简洁地表示为 flex:1)也将起作用——即将 flex-basis 设置为 0,并允许flex items to grow (而不是强迫它们 shrink) 从那里,直到它们的最大宽度。产生相同的结果,只是通过一个不同的路线。)

更长的解释:下面是发生的事情:

  1. 默认情况下,所有内容都有 flex-basis:auto,在这种情况下,这意味着每个弹性项目都以其图像的固有宽度开始弯曲。因此,您的大图像弹性项目具有巨大的弹性基础,而您的小图像弹性项目具有小的弹性基础。
  2. 我们看看弹性项目的 flex-basis 值的总和是否大于容器。他们是(因为你的一些图片很大)。所以,我们必须缩小东西。
  3. 我们收缩每个弹性项目 "fairly",从其 flex-basis 开始,收缩任何必要的部分以使所有项目适合。所以例如例如,每个 项目失去其宽度的 1/4(如果这恰好是使它们完全适合容器的正确部分)。
  4. 现在,我们检查这些 "tentative" 商品尺寸是否违反了商品的 max-width。带有大图像的 flex 项目 可能会 在此状态下违反其 max-width,因为例如即使我们去掉它们大小的 1/4(在我的示例中),它们仍然比它们的 max-width:250px 大得多。对于任何此类违规行为,我们将项目冻结在其最大宽度,然后重新启动收缩过程。 (我们对 min-width 次违规采取了类似的措施。)
  5. 在重新启动的缩小过程中,大图像被冻结在 250px 宽度,较小的图像负责所有的缩小。

因此,如果没有足够的 space 让每个人都拥有 250px 的宽度,您的小型 flex 项目最终不得不完成所有的收缩。 (除非我们受到足够的限制,在第一轮收缩中,大项目将缩小到小于 250px ——例如,如果我们将每个项目缩小 90%,比如说.虽然,然后小项目也将缩小 90%,并且它们将小于它们的 min-width:60px,并且它们将冻结在那个大小,我们将以相同的方式重新启动收缩我在上面描述过)。

如果您好奇,请参阅 the "Resolving Flexible Lengths" chunk of the spec 了解更多详情。

这是 chrome 和 Firefox 之间的渲染差异,但可以通过以下方式轻松修复:

.item { flex: 1 1 0; }

这告诉浏览器所有的 flex 项目应该以 0 宽度开始,并且都以相同的速率增长以填充剩余的 space。

当我查看您的 JSFiddle 时,问题很简单,图像框的大小不包括边框,因为它需要像这样明确说明:

img { box-sizing: border-box; }

img 标签不受 flexbox 的影响,flexbox 只影响它们在你的 JSFiddle 中的父 div (http://jsfiddle.net/brcrnj80/6/) 我认为市场上的每个 CSS 框架都默认包含这个作为全局定义,这让我们忘记了我们需要在需要时自己设置它。