Flexible Box Layout 原理剖析
flex
布局会创建新的格式化上下文 flex formatting context
,flex
容器的子项可以在任何方向上进行布局,并且可以“伸缩”其大小,既可以增长已填充未使用的空间,也可以收缩防止子项溢出。子项的水平和垂直对齐都可以轻松操纵。
在正式开始之前,我们先了解一下排版的一些基础知识。
盒(Box)
排版和渲染的基本单位是盒(Box),一个元素(Element)在排版时可能产生多个盒(Box)。一个 <span></span>
,从源代码角度而言,它是一个标签(Tag);从语义上来讲,它是一个元素(Element);从表现上来看,它是一个盒(Box)。
一个 inline-block
元素可能会产生多个盒,我们可以使用 chrome
调试工具选中元素,在控制台输入$0.getClientRects()
来获取行盒。通常情况下,我们用选择器选中的都是元素,而选不到盒本身,但是也有特例,::first-letter
伪元素可以选到盒,它就是首行的首字(母)。
上图是一个 span
标签包裹的元素,产生了 8 个盒,也就是每一行都是一个行盒。
基本术语
flex container
display
的属性为 flex
或者 inline-flex
的元素
tips:
:: first-line
和 :: first-letter
伪元素不适用于 flex container
flex item
flex container
的所有子元素,对应得是 flex-level box
,而不是 block-level box
tips:
设置
flex
后,flex item
的float
、clear
、vercital-align
属性将失效。具有绝对定位(脱离文档流)的
flex item
不会参与flex
布局。
main axis
flex container
的主轴
cross axis
flex container
的交叉轴
main start
主轴的开始位置
main end
主轴的结束位置
cross start
交叉轴的开始位置
cross end
交叉轴的结束位置
main size
主轴尺寸
cross size
交叉轴尺寸
flex 布局
收集盒进行(hàng)
根据主轴尺寸 mainSize
,把盒分进行;若设置了 nowrap
,强行分配进第一行。
若 flex container
没有设置 mainSize
,则 mainSize
为主轴方向的 size
属性之和。可能是 width
,也可能是 height
,这取决于 flex-direction
的属性值是 row
还是 column
。
计算盒在主轴方向的排布
把主轴方向的剩余尺寸按比例分配给
flex item
若剩余空间为负数,所有
flex
元素为 0,等比压缩剩余元素
① 若 flex item
的 size
属性之和超出了 mainSize
,所有 flex item
置为 0,在主轴方向等比例伸缩。
② 若某一行有剩余空间,且存在 flex item
没有设置主轴方向的 size
属性,width
或者 height
。 该子项 flex item
设置 flex: 1
,所有设有 flex
属性的元素平分剩余空间。
③ 若设置了 wrap
,flex item
的 size
属性之和超出了 mainSize
,则从超出的 flex item
开始放入下一行。
计算盒在交叉轴方向的排布
根据每一行中最大元素尺寸计算行高
根据行高
flex-align
和item-align
,确定元素具体位置
① 交叉轴的尺寸 crossSize
取决于 flex item
在交叉轴方向最大的 size
属性,默认 row
是主轴,则 flex container
的 height
属性无论设置多小,还是会被 flex item
的 height
属性撑开。
② 若交叉轴有剩余空间,所有 flex item
在交叉轴方向平分剩余空间。
以上只讨论了 flex
布局的部分属性情况,可能在某些属性的作用下,文中表述还存在不严谨的地方,还请见谅,也欢迎大家指正。
Animation 源代码请戳这里
flex 属性
flex: 1
是 flex-grow
、flex-shrink
、flex-basis
属性的简写。
flex-grow
| 属性值语法<number>
指定了 flex container
中剩余空间的多少应该分配给项目(flex
增长系数)。
flex-shrink
| 属性值语法只允许<number>
,负值不被允许
指定了 flex item
的收缩规则。flex item
仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink
的值。
flex-basis
| 属性值语法content
或者<'width'>
指定了 flex item
在主轴方向上的初始大小。若不使用 box-sizing
改变盒模型的话,这个属性就决定了 flex item
的内容盒(content-box)的尺寸。
参考
推荐阅读
版权声明: 本文为 InfoQ 作者【大导演】的原创文章。
原文链接:【http://xie.infoq.cn/article/24fd0d92d640f139f5791a983】。文章转载请联系作者。
评论