为啥 flexbox 项目图像根据其初始大小调整大小不同?

Posted

技术标签:

【中文标题】为啥 flexbox 项目图像根据其初始大小调整大小不同?【英文标题】:Why do flexbox item images resize differently according to their initial size?为什么 flexbox 项目图像根据其初始大小调整大小不同? 【发布时间】:2015-04-18 13:53:01 【问题描述】:

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

我在 div 周围有一个红色边框,在 imgs 周围有一个绿色边框。较小图像的绿色边框在较大图像之前缩小。这是为什么呢?

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;

谢谢

【问题讨论】:

我需要澄清一下。你的意思是为什么它们超出了弹性容器的边界?或者为什么它们以不同的速度缩小到最低限度?因为看着你的小提琴(在 Chrome 中)它们都同时调整大小,即使当我运行小提琴并且最大的图像仍在填充时,它们都会同时调整大小。较小的图像似乎确实首先达到了最小宽度,但这可能是我的感知问题,因为图像接近最小值。 值得指出的是,有一个 webkit 错误(所有支持 flexbox 的 safari 版本,包括移动设备)阻止 flex 容器在遇到 flex 项的最小宽度时包装 flex 项 (bugs.webkit.org/show_bug.cgi?id=136041 )。这是一个非常讨厌的错误,使得尝试使用带有min-width flex 项目的 flexbox 几乎毫无用处(由于 safari 在移动设备上无处不在)。 @fnostro (至少在 FF 中)直到蘑菇相当小,花才开始调整大小。这不是chrome的情况吗(目前无法访问chrome) 好的——基于此,我会说这是 FF 的渲染问题——正如@Adam 建议的那样,您可能希望确保您的 css 包含所有不同风格的 flex 定义。请参阅底部的A Guide to flexbox over at CSS Tricks 请参阅Prefixing FlexBox部分 我没有方便的 IE11 来测试它,但我发现网上提到 IE11 在弹性项目上使用 max-width 时会出现更大的问题。 【参考方案1】:

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

img  box-sizing: border-box; 

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

【讨论】:

【参考方案2】:

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

修复:如果你给每个弹性项目相同的弹性基础,例如flex-basis:250px(与他们的max-width 相同),您可能会得到您正在寻找的结果。更新小提琴:http://jsfiddle.net/brcrnj80/10/

(如另一个答案中所述,flex: 1 1 0(可以更简洁地表示为flex:1)也可以工作——将flex-basis设置为0,并允许弹性项目增长(而不是强制它们收缩)从那里直到它们的最大宽度。产生相同的结果,只是通过不同的路线。)

更长的解释:会发生以下情况:

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

因此,如果没有足够的空间让每个人都拥有 250 像素的宽度,那么您的小型 flex 项目最终将不得不进行所有的收缩。 (除非我们受到足够的限制,以至于在第一轮收缩中大项目将被收缩到小于 250 像素 - 例如,如果我们将每个项目收缩 90%。虽然,那么小物品也将缩小 90%,它们将小于它们的min-width:60px,它们将被冻结在那个尺寸,我们将以我上面描述的相同方式重新开始缩小)。

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

【讨论】:

虽然它们在当前情况下可能看起来具有相同的效果,但flex: 1flex: 1 1 auto 相同,而不是flex: 1 1 0 不,“flex:1”确实等同于“flex:1 1 0”。虽然 flex-basis 的初始值确实是“auto”,但如果您在没有明确 flex-basis 的情况下提供“flex”速记值,则 flex 速记会将其设置为 0(技术规范中的“0%”)。规范参考:dev.w3.org/csswg/css-flexbox-1/#valdef-flex-flex-basis 和 dev.w3.org/csswg/css-flexbox-1/#flex-initial 特别是“当从 flex 速记中省略时,其 [flex-basis's] 指定值为 0%。 伟大的参考,在我个人看来并没有什么意义,但规范不会说谎。谢谢。 成功了。最后,我看到了 flex-basis 何时发挥作用的示例。谢谢。【参考方案3】:

之前有人在这里发布了答案(我几乎是肯定的,我不确定为什么它被删除了?)。

是的,这是 chrome 和 firefox 之间的渲染差异,但很容易通过以下方式修复:

.item  flex: 1 1 0; 

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

【讨论】:

以上是关于为啥 flexbox 项目图像根据其初始大小调整大小不同?的主要内容,如果未能解决你的问题,请参考以下文章

Flexbox 图像在浏览器中的大小调整不同

在 CSS FlexBox 布局中自动调整图像大小并保持纵横比?

为啥弹性项目不缩小超过内容大小?

为啥当我滚动浏览 UITableView 时图像会不断调整大小?

Internet Explorer - Flexbox 图像比例

Fabricjs HTML5 Canvas:为啥图像大小调整得这么差?