为什么 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) 从那里,直到它们的最大宽度。产生相同的结果,只是通过一个不同的路线。)
更长的解释:下面是发生的事情:
- 默认情况下,所有内容都有
flex-basis:auto
,在这种情况下,这意味着每个弹性项目都以其图像的固有宽度开始弯曲。因此,您的大图像弹性项目具有巨大的弹性基础,而您的小图像弹性项目具有小的弹性基础。
- 我们看看弹性项目的
flex-basis
值的总和是否大于容器。他们是(因为你的一些图片很大)。所以,我们必须缩小东西。
- 我们收缩每个弹性项目 "fairly",从其
flex-basis
开始,收缩任何必要的部分以使所有项目适合。所以例如例如,每个 项目失去其宽度的 1/4(如果这恰好是使它们完全适合容器的正确部分)。
- 现在,我们检查这些 "tentative" 商品尺寸是否违反了商品的
max-width
。带有大图像的 flex 项目 可能会 在此状态下违反其 max-width
,因为例如即使我们去掉它们大小的 1/4(在我的示例中),它们仍然比它们的 max-width:250px
大得多。对于任何此类违规行为,我们将项目冻结在其最大宽度,然后重新启动收缩过程。 (我们对 min-width
次违规采取了类似的措施。)
- 在重新启动的缩小过程中,大图像被冻结在 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 框架都默认包含这个作为全局定义,这让我们忘记了我们需要在需要时自己设置它。
我有四张图片:两张小的,两张大的(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) 从那里,直到它们的最大宽度。产生相同的结果,只是通过一个不同的路线。)
更长的解释:下面是发生的事情:
- 默认情况下,所有内容都有
flex-basis:auto
,在这种情况下,这意味着每个弹性项目都以其图像的固有宽度开始弯曲。因此,您的大图像弹性项目具有巨大的弹性基础,而您的小图像弹性项目具有小的弹性基础。 - 我们看看弹性项目的
flex-basis
值的总和是否大于容器。他们是(因为你的一些图片很大)。所以,我们必须缩小东西。 - 我们收缩每个弹性项目 "fairly",从其
flex-basis
开始,收缩任何必要的部分以使所有项目适合。所以例如例如,每个 项目失去其宽度的 1/4(如果这恰好是使它们完全适合容器的正确部分)。 - 现在,我们检查这些 "tentative" 商品尺寸是否违反了商品的
max-width
。带有大图像的 flex 项目 可能会 在此状态下违反其max-width
,因为例如即使我们去掉它们大小的 1/4(在我的示例中),它们仍然比它们的max-width:250px
大得多。对于任何此类违规行为,我们将项目冻结在其最大宽度,然后重新启动收缩过程。 (我们对min-width
次违规采取了类似的措施。) - 在重新启动的缩小过程中,大图像被冻结在 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 框架都默认包含这个作为全局定义,这让我们忘记了我们需要在需要时自己设置它。