Categories
程式開發

Flexible Box Layout 原理剖析


flex 布局会创建新的格式化上下文 flex formatting context,flex 容器的子项可以在任何方向上进行布局,并且可以“伸缩”其大小,既可以增长已填充未使用的空间,也可以收缩防止子项溢出。子项的水平和垂直对齐都可以轻松操纵。

在正式开始之前,我们先了解一下排版的一些基础知识。

盒(Box)

排版和渲染的基本单位是盒(Box),一个元素(Element)在排版时可能产生多个盒(Box)。一个 ,从源代码角度而言,它是一个标签(Tag);从语义上来讲,它是一个元素(Element);从表现上来看,它是一个盒(Box)。

一个 inline-block 元素可能会产生多个盒,我们可以使用 chrome 调试工具选中元素,在控制台输入$0.getClientRects() 来获取行盒。通常情况下,我们用选择器选中的都是元素,而选不到盒本身,但是也有特例,::first-letter 伪元素可以选到盒,它就是首行的首字(母)。

Flexible Box Layout 原理剖析 1

上图是一个 span 标签包裹的元素,产生了 8 个盒,也就是每一行都是一个行盒。

基本术语

Flexible Box Layout 原理剖析 2

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 布局的部分属性情况,可能在某些属性的作用下,文中表述还存在不严谨的地方,还请见谅,也欢迎大家指正。

flex 属性

flex: 1 是 flex-grow、flex-shrink、flex-basis 属性的简写。

flex-grow | 属性值语法

指定了 flex container 中剩余空间的多少应该分配给项目(flex 增长系数)。

flex-shrink | 属性值语法只允许 ,负值不被允许

指定了 flex item 的收缩规则。flex item 仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。

flex-basis | 属性值语法 content 或者

指定了 flex item 在主轴方向上的初始大小。若不使用 box-sizing 改变盒模型的话,这个属性就决定了 flex item 的内容盒(content-box)的尺寸。

参考

CSS Flexible Box Layout Module Level 1

推荐阅读

Flex 布局教程:语法篇Flex 布局教程:实例篇