个人感觉应该跟这个 section 有关
https://www.w3.org/TR/css-sizing-3/#cyclic-percentage-contribution If the box is replaced, a cyclic percentage in the value of any max size property or preferred size property (width/max-width/height/max-height), is resolved against zero when calculating the min-content contribution in the corresponding axis.
尝试来解释一下:
前提知识点:div 和 img 的 display 计算值虽然都是 block ,但是 CSS 内部还是区别对待 img 的,因为它是 replaced element 。
套多层 flex 起到的效果和 width:min-content 一样,简单说就是这个 container 的宽度由子元素 的 min-content 来贡献。虽然 .icon 已经有明确的 width 定义,但它的 max-width 也会影响它的 min-content 最终是多少,而 max-width 如果是百分值,也就是它需要先知道父容器( containing block )的 size ,所以这里就产生了循环依赖。CSS Box Sizing Module Spec 就规定了这种情况,解法分 replaced element 和 non-replaced element 。
non-replaced element 在计算 min-content / max-content 内在盒子大小时,遇到百分比或循环依赖值,直接就把整个值当作是没定义一样,即,使用其 initial value 来计算。div 的 max-width initial value 是 auto ,width:16px + max-width:auto 得到的 min-content 就是 16px 。
replaced element 在计算 max-content 时也是一样,但计算 min-content 时不同,循环依赖值会直接当成 0 来对待。width:16px + max-width: 0 得到的 min-content 就是 0 ,所以在父容器计算宽度时,img 贡献了 0 。
这里的 0 / auto 只会影响解盒子的 min/max-content 的流程,盒子本身的 sizing 过程百分比依然会被遵守,即,max-width:100% 在以 0 对待并算完父容器的宽度后再以百分比算出其值然后作用于 img 上。span 中的字符总宽度 hello word!!! 是 111.25px ,因此含 img 的 .item 算得宽度 111.25px ,img 最终得到 max-width:111.25px width:16px 宽度仍然是 16px 。
img 加 max-width: 100% 后在贡献宽度的时候贡献了 0 , 在分配宽度的时候还占 16px ,所以整体 size 就不够分了,没人 flex-shrink 所以就溢出了。