flex 布局中的问题
最近在开发一个移动端适配的 H5 应用时,遇到了一个布局上的问题。简单描述如下:
页面从上到下排列有多个元素,其中有几张图片。在高宽比较大的手机上展示时(也就是比较长的手机,例如 iPhone X),布局没什么问题。但在一些小手机上,屏幕的纵轴无法容纳这么多元素。特别当微信浏览器中出现下方的导航栏时,高宽比被进一步减小,纵轴空间更加局促了。
这个问题看起来不难。使用 flex 布局,让图片元素在小屏幕上自动控制高度,自适应等比缩放不就 OK 了吗?于是写出了如下的代码:
|
|
在 Chrome 中使用移动设备仿真,各种不同高度下的效果都 OK 了。结果用自己的 iPhone 再看却出了问题:图片没有按照预想的那样自动调整高度,而是保持着原始图片的大小。
于是我开始搜索有关 flex 布局与 min/max 样式之间如何相互作用的资料。这里先给出最后的解决方案:给 .image-wrap
元素加上 flex-basis: 688px
样式。
flex-basis 默认值:auto
为了彻底弄明白问题出在哪里,有必要进一步了解 flex-basis
属性。以前我只是简单的以为它大概就和 width
属性一样,设置不设置都没关系。研究过后才发现这个属性有着诸多细节。(这里为了简化说明,只探讨 flex-direction: row
的情形)
在 flex 布局中,一个 flex 子项的最终尺寸是基础尺寸、弹性增长或收缩、最大最小尺寸限制共同作用的结果。其中:
- 基础尺寸由
flex-basis
与box-sizing
盒模型共同决定; - 弹性增长指的是
flex-grow
属性,弹性收缩指的是flex-shrink
属性。这里不做过多阐述,详情可参考:flex-grow,flex-shrink; - 最大最小尺寸限制指的是
min-width
/max-width
等 CSS 属性。
其中优先级为:最大最小尺寸限制 > 弹性增长或收缩 > 基础尺寸。
按照这个理论,在上文的例子中,我已经设置好了 max-height
、min-height
、flex-grow
、flex-shrink
,虽然没有设置 flex-basis
,也不应该影响结果才对。
我在查看了更多资料之后,发现 flex-basis
还有许多细节:
- 在 flex 布局中,
flex-basis
就同非 flex 布局中width
属性表现一样; - 在 flex 布局中,若同时设置了确定数值的
flex-basis
与width
,则width
属性会被忽略; - 当
flex-basis
值为auto
时(默认值),子项的基本尺寸根据其自身的尺寸决定。更具体一点地说,由box-sizing
、width
、min-width
、max-width
以及元素内容共同决定。
再来看上文的例子,我没有设置 flex-basis
,所以它是默认值 auto
,flex 子项的 flex-basis
根据其自身的尺寸决定。对于 .image-wrap
元素,根据我所设置的 CSS 样式:
|
|
它的高度应该是由 box-sizing
盒模型、min-height
、max-height
属性共同决定(注意这里我没有设置 height
)。看来在这种情况下,Chrome 和 Safari 下对于最终效果的处理有些不一致。
在使用弹性布局时,最好是明确给出 flex-basis
的值。