共计 3995 个字符,预计需要花费 10 分钟才能阅读完成。
Flexbox 是一种 CSS 布局机制,能够说是目前浏览器原生反对的最好、应用最宽泛的布局机制了。本文通过一些例子来阐明 Flexbox 布局的工作原理,能够让咱们更好的应用 Flexbox。
与 CSS Grid 能够同时在横向和纵向两个方向进行布局不同,Flexbox 只能在繁多方向上进行布局,即要么横向,要么纵向。所谓布局,其实就是空间的调配过程,也就是说计算元素尺寸和容器残余空间尺寸的过程。
Flexbox 的布局原理
整个布局过程咱们能够简略的总结如下:
- 计算 flex 容器内的可用空间。整个容器的尺寸减去容器的 border、padding 等所得的残余空间尺寸。
- 计算每个 flex 元素的 flex base 尺寸和元素的假如尺寸。具体计算方法是取 flex-basis、min-width 和 flex 元素内容尺寸的较大者。flex base 尺寸是 flex 元素须要的最小尺寸,这个尺寸不能小于元素内容的尺寸。元素的假如尺寸是指在 flex 因子失效前元素的尺寸,flex 因子失效后可能导致元素产生伸缩。
- 计算容器内所有 flex 元素的假如尺寸总和。
- 将所有元素的假如尺寸总和与容器内可用空间尺寸做比拟,来确定 flex 因子,也就是说当假如尺寸总和超过容器内可用空间尺寸时,应用 flex-shrink,否则应用 flex-grow。在同一时间,flex-shrink 和 flex-grow 只有一个失效。
所谓 flex 因子,简略来说就是放大和放大。浏览器在进行 flexbox 布局时会先确定应用哪种 flex 因子,而后再依据选用的 flex 因子来对元素尺寸进行调整。
在进行调整的时候,就会波及到一个残余空间的计算问题。如果 flex 元素明确指定了尺寸大小(definite size,比方设置了 width),那么这个元素就是不可伸缩的。如果没有显式指定尺寸,则会依照下面第 2 步那样计算假如尺寸。残余空间的尺寸就是容器内的可用空间尺寸减去这些元素的尺寸之和。
例子阐明
咱们有如下 dom 构造:
<div id="flex">
<div id="a">Antidisestablishmentarianism</div>
<div id="b">B</div>
<div id="c">Cherries jubilee</div>
<div id="d">D</div>
<div id="e">E</div>
</div>
款式如下:
[id=flex] {
font-weight: 300;
display: flex;
outline: 1px dashed #555;
width: 1200px;
margin: 3rem auto;
}
/* 其余款式已省略 */
页面展现成果如下:
咱们没有设置元素的 flex
款式属性,默认值是 0 1 auto
。flex
款式属性是 flex-grow
、flex-shrink
和 flex-basis
这三个款式属性的简写模式。0 1 auto
别离对应为 flex-grow
、flex-shrink
和 flex-basis
的值。
通过取值能够看到,因为咱们禁止了放大和膨胀,并且 flex-basis
的值是 auto
,浏览器就应用元素的最大内容尺寸来计算所有元素的尺寸总和,比容器的尺寸(1200px)小,所有会有额定的残余空间。
对于 flex
这个款式属性,咱们额定做一些阐明。flex
属性能够接管起码一个、最多三个属性值。
当只有一个属性值的时候,flex
的工作模式是这样的 <number> 1 0
。即 flex: 2
最终的后果是 flex: 2 1 0
。
当有两个属性值的时候,第一个值会被解析为 flex-grow
,第二个值如果是数字,则会被解析为 flex-shrink
,如果是一个非法的宽度值则会被解析为 flex-basis
。即 flex: 1 0
解析为 flex: 1 0 0
,而 flex: 1 20rem
则被解析为 flex: 1 1 20rem
。
当有三个属性值的时候,第一个值被解析为 flex-grow
,第二个值必须为数字,且会被解析为 flex-shrink
,第三个值则必须是非法的宽度值,被解析为 flex-basis
。
设置 flex-grow
咱们减少如下款式设置:
[id=flex] > div {flex: 1;}
实际上等同于 flex: 1 1 0
,即 flex-grow: 1
。从后面的例子咱们能够看到,所有元素的假如尺寸之和是小于容器残余空间尺寸的,所以浏览器会应用 flex-grow
来作为 flex 因子,因为咱们设置了 flex-grow: 1
,因而浏览器会等比放大所有的元素。如下图:
实际上浏览器会循环通过上面的公式来计算每个元素的最终尺寸:
以后元素伸缩值 = (以后残余空间 - 所有残余元素的 flex-grow 值的和) * 以后元素的 flex-grow 值
在下面的例子中,容器的残余空间为 1200px,因而,通过公式计算:
(1200 ÷ ( 1 + 1 + 1 + 1 + 1) ) × 1 = 240
元素 A 的最终尺寸为 240px + flex-basis = 240px + 0 = 240px
。然而,因为 Antidisestablishmentarianism
这个单词比拟长,理论会占用 417px
的空间大小,因而元素 A 的最终尺寸为 417px
。
此时,在计算元素 B 的尺寸时,残余空间为 1200px - 417px = 783px
。元素 B 的伸缩值为:
(783 ÷ ( 1 + 1 + 1 + 1) ) × 1 = 195.75 0 + 195.75 = 195.75
同理,元素 C、D、E 的伸缩值别离为:
C: (587 ÷ ( 1 + 1 + 1) ) × 1 ) = 195.67
D: (391.33 ÷ ( 1 + 1) ) × 1 = 195.665
E: (391 - 195.665 ÷ 1) × 1 = 195.335
总结来说,浏览器从残余空间中减去曾经调配的空间,而后计算下一个 flex 元素的伸缩值和最终大小。
差异化的 flex-grow
咱们批改一下元素的 flex-grow
值:
div > :not([id=c]) {flex: 1;}
[id=c] {flex: 5;}
此时,页面展现成果如下:
各元素的伸缩值计算如下:
A: 417px
B: (783 ÷ ( 1 + 1 + 5 + 1) ) × 1 = 98
C: (685 ÷ ( 5 + 1 + 1) ) × 5 = 490
D: (195 ÷ ( 1 + 1) ) × 1 = 97.5
E: (97.5 ÷ 1) × 1 = 97.5
设置 flex-basis: auto
后面的例子里,咱们都设置了 flex-basis
的值为 0,当初咱们设置 flex-basis: auto
,再来看看元素尺寸是如何计算的。
删除其余元素的 flex 指定,批改款式如下:
[id=c] {flex: 5;}
此时等价于其余元素是 flex: 0 1 auto
,元素 C 是 flex: 5 1 0
。展现成果如下:
在后面的例子中,所有元素都是 flex-basis: 0
,当初设置为 A、B、D、E 都设置成了 flex-basis: auto
。因而,元素 A、B、D、E 都会应用元素内容的尺寸来计算。
因而,残余残余可调配空间大小为:
1200 - (417 + 33 + 35 + 30) = 685
因为元素 C 是惟一可伸缩的元素,因而它的伸缩值为 685。
设置 flex-shrink
当初咱们做一些调整,让所有 flex 元素的尺寸总和大于容器的可用空间尺寸,使得 flex-shrink 失效。
款式调整如下:
:not([id=a]) {flex-shrink: 1;}
[id=a] {flex-shrink: 5;}
div > div {flex-basis: 500px;}
能够看到,所有元素 flex-grow: 0
,元素 A flex-shrink: 5
,其余元素 flex-shrink: 1
,所有元素总尺寸 2500px。
显示成果如下:
因为元素尺寸总和超过了容器可用尺寸(1200px),因而 flex-shrink 将会失效。
元素 A 的伸缩值为:
(1300 ÷ ( 5 + 1 + 1 + 1 + 1) ) × 5 = 722.22
则元素 A 的理论尺寸计算为:
500 - 722.22 = -222.22
能够看到得出的是负值。如果元素 A 是空元素,那么最终尺寸会是零。本例中,元素 A 的尺寸就是起内容的尺寸,大略 34px。
确定了元素 A 的尺寸之后,容器残余空间尺寸为 1200 - 34 = 1166
。其余元素的伸缩值计算为:
B: (1166 ÷ ( 1 + 1 + 1 + 1) ) × 1 = 291.5
C: (874.5 ÷ ( 1 + 1 + 1) ) × 1 = 291.5
D: (583 ÷ ( 1 + 1) ) × 1 = 291.5
E: (291.5 ÷ 1) × 1 = 291.5
值得注意的一点是,如果 flex-grow
和 flex-shrink
的取值都为 0,那么元素即不会放大也不会放大,当所有元素的尺寸总和超过容器空间之后,就会产生溢出成果。
设置 flex-wrap
当所有元素的尺寸总和超过容器空间之后,就会产生溢出成果。咱们能够通过设置 flex-wrap: wrap
来是超出的元素换行。
咱们调整下款式:
div > div {flex-basis: 500px;}
[id=flex] {flex-wrap: wrap;}
显示成果如下:
咱们能够看到,因为 flex-basis: 500px
且默认的 flex-grow: 0
,因而每一行的开端有 200px 的残余空间。
咱们能够通过设置 flex-grow: 1
来让元素占满残余空间。
div > div {flex: 1 1 500px;}
此时显示成果如下:
能够看到,每行的残余空间都被占满了。
总结
Flexbox 布局有时候会有一些简单和难以了解。在理论应用过程中,咱们须要牢记如下几点:
- Flexbox 只在繁多方向上调配空间,行或者列。
- flex-basis 定义了元素的最小尺寸,有时候元素的内容尺寸可能会比 flex-basis 定义的尺寸大。
- 浏览器同时只会应用 flex-grow 或者 flex-shrink 来排列元素,不会同时应用。
- 理论应用 flex-grow 还是 flex-shrink 取决于元素尺寸总和与容器残余空间的大小。
- 浏览器依据 flex 因子以及元素自身设置的系数来调配每个元素的空间。
常见面试知识点、技术计划剖析、教程,都能够扫码关注公众号“众里千寻”获取,或者来这里 https://everfind.github.io/po…。