Flex Container 下的 img 的奇怪表现

Flex Container 下的 img 的奇怪表现

在 Chrome / Safari 上, 如果一个容器 display: flex; 有固定的宽度, 同时含有一个 <img> 或者 <canvas> 元素, 后者有可能会被拉伸. 如果后者宽度大于容器, 并且有设置 width 和 height 属性, 并以 max-width: 100%; height: auto; 的形式自适应, 则容器可能会占据超过元素显示高度的高度 – 容器的高度为 img / canvas 的 height 属性值. 在 Firefox 上没有观测到类似的状况.

这是一个 demo, <img><canvas> 的 width, height 均设置为 160, 容器宽度为 80. img 和 canvas 均被拉伸, 高度为 160, 也就是属性中的值. 如果加个 margin: auto; 会导致 img / canvas 保持本来的长宽比, margin 填满剩余空间达到垂直居中的 … 但是容器高度还是 160.

https://jsfiddle.net/nullaber/u4jd7xmL/40/embedded/result,html,css

Demo 在 Chrome, Safari 和 Firefox 上的对比
Demo 在 Chrome, Safari 和 Firefox 上的对比

于是这里发生了什么呢? 首先已知的状况有: align-self 或者 parent 的 align-items 设置为 flex-start 之类的值可以解决这个问题. 然后关于 align-items 的初始值, 参见 MDN:

normal

The effect of this keyword is dependent of the layout mode we are in:

  • For flex items, the keyword behaves as stretch.

align-items: CSS - MDN

也就是说 flex 下面 align-items 的默认效果为 stretch. 在这一点上, 如果 Firefox 下 img 没有 height: auto; 的样式(但是含有 max-width 或者 width), 那么 img 会呈现为拉伸状态, 同 Chrome 表现一致. 现在 img 有了 height: auto;, Firefox 重新计算了 img 的高度.

在这个基础上还能影响到 img 宽度的大概还有 flex-basis.

唔, Firefox 和 Chrome 对 flex-basis 的处理不太一样 … 而且 Chrome 还不支持 content 值. 暂缓一下追踪进度, 先忙点别的.

// Todo …

关于原本问题的相关讨论可以查看 StackOverflow: https://stackoverflow.com/questions/37609642/why-does-flexbox-stretch-my-image