关于这个Flex布局,请大家帮忙分析下?

演示Demo

图中 一个flex容器内部有四个div元素,
div内部的img的宽度设置为100px。

默认情况下flex-wrap=nowrap flex子项会一行显示且不允许换行,因此可能会出现宽度溢出的问题。

问题1

“因此可能会出现宽度溢出的问题” : 这个宽度溢出应该也是有 条件的吧? 虽然flex子项的累计宽度大于flex容器,但是默认情况下 flex子项是允许收缩的。 如果收缩以后还是超出flex容器的宽度,那才会出现溢出。
我的这个理解对吗?

问题2

基于问题1, 上面的四个flex 子项div, 为什么他们没有收缩 适应fle容器的宽度,而是选择了溢出?
flex子项他们有最小宽度限制吗? 我看div和img的min-width都是0px,并没有最小宽度限制。

问题3

为什么css 中设置了

img {
  max-width: 100%;
}

就能让四个图片收缩到 适应flex容器的宽度,而不会出现溢出的情况。

b

阅读 3.4k
5 个回答

首先,我发现Firefox对于flex的调试更好一些,题主可以试试用火狐看
image.png
如图,你会发现有个“最小尺寸” 英文Minimum Size,所以4个div不会收缩
mdn中可见https://developer.mozilla.org/en-US/docs/Web/CSS/flex#initial

It shrinks to its minimum size to fit the container

关于为什么会有这个Minimum Size
请研究https://drafts.csswg.org/css-flexbox/#min-size-auto
规范的这块部分。我看了一会,并没有看明白。。。
可以搜索min-content Minimum Size研究一下
不过可以断定的是,min-width是0px只是个computed计算里显示的值,如果你手动指定min-width为0px,就会收缩了。我记得我曾经也碰见过一个类似问题,将computed里显示的默认值变成手动设置的css代码,效果就不一样了。

参考
https://medium.com/the-crazy-coder/the-mystery-of-css-flex-la...
https://www.bigbinary.com/blog/understanding-the-automatic-mi...
https://fantasai.inkedblade.net/style/discuss/flexbox-min-size/
https://firefox-source-docs.mozilla.org/devtools-user/page_in...

The second reason is that flexbox prevents small items from shrinking to zero size during this removal of negative free space. The items will be floored at their min-content size — the size that they become if they take advantage of any soft wrapping opportunities available to them.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible...

调试css真的是个黑盒,里边老多变量的值和逻辑都是不展示出来的。只能看规范猜。等有时间了研究一下chromium的css渲染实现

flex 的成员大小计算有一个比较重要的属性就是 flex-basis,如果没有设置 flex-basis 属性,那么是会根据成员自身进行推算。

可能会影响这个推算的成员属性大概有 width, max-width, min-width 还有成员的 min-content, max-content。

例如成员没有设置 width 这些属性,那么优先就会取 max-content 去计算。以文本为例,文本其 max-content 就是一行文本下的总长度。计算后还可能会对比 min-content,来保证最后计算出来宽度不能小于 min-content,默认文本的 min-content 是一个字符的宽度,如果设置了 white-space: nowrap; 那么 min-content 会变为 max-content 一样的大小。如果这个时候设置了 min-width 属性,那么就会比较 min-width,而不去比较 min-content 了。举这个例子主要是说明其中不同属性互相影响的复杂性。这里有一个 overflow 属性影响计算的例子(https://codepen.io/changli/pen/poGMjKj)

当同时设置这些属性时,那些属性优先,那么属性被忽略,这其实就涉及到 flex 布局的实现了,这个可以看规范(https://drafts.csswg.org/css-flexbox/)

从应用的角度看,主要知道哪些属性会影响到计算就可以了,太过深入容易丧失对 css 的乐趣。

我的猜想

flex子元素上的属性flex默认值
flex-basis: auto;
flex-grow: 0;
flex-shrink: 1;

这里子元素的宽度的计算

  1. 先计算flex-basis:auto的值,这里就是元素的内容大小(没有显示的设置width)。flex子元素的大小是img的大小,但是width:100%; 并不能获知它的大小,因此此时flex子元素的大小我们不知啊,所以它的大小应该是自身的固定尺寸
  2. flex子元素的宽度加起来比父元素的宽度大,然后再收缩,但是不能低于min-width。那么min-width是什么的?我们没有显示设置,应该就是它的min-content,就是img的宽度,它的宽度因为设置成了百分比,所以min-width: 0,所以可以尽可能的缩小。 它们的flex-shrink都是1,收缩的大小都是一样的,所以收缩之后各个图片的大小关系和img固定尺寸的大小关系是一样的。

此时,各个flex子元素的宽度就确定了,那么照片的大小(width:100%)也就可以计算出了,就是此时flex子元素的宽度,这就不会有溢出了。

是我太low了嘛?我怎么感觉前面大佬回答的太高大上了点,莫非我没看懂题目?
首先第一个问题和第二个问题
你的img是包含在div中的,所以flex的子项是div!!!
然后img设置宽度为100px,把div撑开了,所以它做不到自适应宽度,我说不出什么原理,但是从经验来说,你写死的宽度比任何默认值的优先级都高,那就会基于这个写死的宽度来调整样式

最后一个问题
把img宽度设置成max-width: 100%,那就是img的最大宽度是父元素div的宽度,div没有声明宽度,那就是按flex的规则来,子项均分,每份92.5px,这就是div的宽度.所以img的最大宽度就是92.5px,
那为什么每张图最终呈现的就是92.5呢,因为每一张图实际像素都大于92.5px,自然按最大的来
image.png

新手上路,请多包涵

image.png 和上面兄弟说的一样 你只要把其中一项的100px改为100%就好了

推荐问题
宣传栏