内容简介:css 的 flex 弹性布局,广泛应用在当今的页面开发中,其弹性伸缩的的灵活性非常擅长于开发有响应式需求的网站。但是有很多时候,其灵活性也会让人疑惑,特别是确定尺寸时,基本上是靠不断尝试。为了在开发时更加得心应手,下面将以主轴方向上,也就是默认布局方向上的成员宽度值计算为例子进行研究。flex 是弹性的伸缩布局,具有伸和缩两个特性,下面在研究时也以伸和缩两种状态来进行研究。 在开始之前,先说一下一些定义,类名 container 是 flex 容器, 类名 item 是 flex 的成员对象,每个成员对象
前言
css 的 flex 弹性布局,广泛应用在当今的页面开发中,其弹性伸缩的的灵活性非常擅长于开发有响应式需求的网站。但是有很多时候,其灵活性也会让人疑惑,特别是确定尺寸时,基本上是靠不断尝试。为了在开发时更加得心应手,下面将以主轴方向上,也就是默认布局方向上的成员宽度值计算为例子进行研究。
准备
flex 是弹性的伸缩布局,具有伸和缩两个特性,下面在研究时也以伸和缩两种状态来进行研究。 在开始之前,先说一下一些定义,类名 container 是 flex 容器, 类名 item 是 flex 的成员对象,每个成员对象内嵌了自已的内容。每个成员都设置了相应的外边距、边框、内边距,为了方便表述把每个成员的外边距宽度的左右宽度和表述为 margin,类似的表述为 border、padding,在下面的计算中会有提及。最后把每个成员的内容区域宽度表述为 content。在下面的例子中我们会发现,成员的最终宽度大小是由成员的 width flex-basic 和 content 值共同决定,在不同状态下也会分别受到 flex-grow 和 flex-shrink 的影响
伸
下面的 flex 布局中设置了 6 个成员,每个成员都设置了不同的 width flex-basic content flex-grow 值
<div class="wrapper"> <h1>test</h1> <style> .container { display: flex; background-color: #915151;} .item { height: 80px; text-align: center; background-color: rgb(214, 120, 52);border-radius: 1em; border: 5px solid #000;text-align: left;margin: 15px; padding: 10px } </style> <div class="container"> <div class="item" style="flex-grow: 1;width: 100px; flex-basis: 0"> <div style="width: 40px"></div> </div> <div class="item" style="flex-grow: 0; width: 250px; flex-basis: 200px"> <div style="width: 300px"></div> </div> <div class="item" style="flex-grow: 2; flex-basis: 200px"> <div></div> </div> <div class="item" style="flex-grow: 2; width: 70px"> <div></div> </div> <div class="item" style="flex-grow: 2;"> <div style="font-family: monospace;">12345678910111213141516</div> </div> <div class="item" style="flex-grow: 3; width: 200px;"> <div style="width: 100px"></div> </div> </div> </div>复制代码
下面是生成布局的截图,包括了每个成员的尺寸
最内层的区域就是成员的大小区域,也就是成员的宽度和高度值,从宽度值可以看出,有的元素的宽度值和成员的 content 大小一样, 有的和成员的 width 值一样,有的和两者都不同,下面将通过公式来计算各个成员的最终宽度值。
由于不是每个成员都设置了相应的 flex-basis、width 和 内容的 width 值,所以我先定下下面的规则来补充缺失的参数值,设置 t-flex-basis 为转化的 flex-basis 值, t-width 为转化的 width 值,t-content 为转化的 content 值
- 成员的 flex-basis 值存在, 那么 t-flex-basis 值就是该值,如果不存在,那么 t-flex-basis 值就是 t-width 的值
- 成员的 width 值存在, 那么 t-width 的值就是该值,如果不存在,,那么 t-width 值就是 t-content 的值
- 成员的 content 设置了 width 值, 那么 t-content 的值就是该值,如果不存在, 那么 t-content 值就是内部的首选最小尺寸值,像成员 3, 4 内部没有字符,那么其 t-content 就是 0,而成员 5 有一串不断行的字符,我故意把字体设置为等宽字体,在我的浏览器中每个字符是 6.5px,这里有 23 个字符,所以 t-content 就为 149.5px
通过以上规则,就可以把成员的参数值转化为下表的数据
下面可以开始计算最终宽度值
计算步骤
- 获取剩余空间
- 分配剩余空间
- 找出不符合分配的成员,重新计算分配空间
获取剩余空间
剩余空间 = 容器可分配空间 - 每个成员(margin + border + padding + t-flex-basis)的和
在我这里的容器宽度是 1349px,这个也是这里的容器可分配空间
剩余空间 = 1349 - (30 + 10 + 20 + 0) - (30 + 10 + 20 + 200) - (30 + 10 + 20 + 200) - (30 + 10 + 20+ 70) - (30 + 10 + 20 + 149.5) - (30 + 10 + 20 + 200) = 169.5
分配剩余空间
分配的剩余空间 = 剩余空间 * (当前成员的 flex-grow) / 待分配成员的 flex-grow 值之和
item1 分配的剩余空间 = 169.5 * 1 / (1 + 0 + 2 + 2 + 2 + 3) = 16.95
item2 分配的剩余空间 = 169.5 * 0 / (1 + 0 + 2 + 2 + 2 + 3) = 0
item3 分配的剩余空间 = 169.5 * 2 / (1 + 0 + 2 + 2 + 2 + 3) = 33.9
item4 分配的剩余空间 = 169.5 * 2 / (1 + 0 + 2 + 2 + 2 + 3) = 33.9
item5 分配的剩余空间 = 169.5 * 2 / (1 + 0 + 2 + 2 + 2 + 3) = 33.9
item6 分配的剩余空间 = 169.5 * 3 / (1 + 0 + 2 + 2 + 2 + 3) = 50.85
找出不符合分配的成员,重新计算分配空间
所谓不符合分配的成员指的是 (分配的剩余空间 + t-flex-basis) < min(t-content, t-width)
当成员不符合分配时,那么该成员的最终值就是 t-content 和 t-width 中的最小值
否则成员的最终值就是:分配的剩余空间 + t-flex-basis
通过比较可以得到 item1 不符合分配
item1 (0 + 16.95) < min(t-content,t-width) = 40
所以 item1 的最终宽度是 40
由于 item1 如果是按分配应该是 16.95,现在是 40,多占据了 23.05
所以要重新分配空间,分配的空间中要减少相应比例的空间
item2 重新分配后的剩余空间 = 0 - 23.05 * 0 / (0 + 2 + 2 + 2 + 3) = 0
item3 重新分配后的剩余空间 = 33.9 - 23.05 * 2 / (0 + 2 + 2 + 2 + 3) = 28.78
item4 重新分配后的剩余空间 = 33.9 - 23.05 * 2 / (0 + 2 + 2 + 2 + 3) = 28.78
item5 重新分配后的剩余空间 = 33.9 - 23.05 * 2 / (0 + 2 + 2 + 2 + 3) = 28.78
item6 重新分配后的剩余空间 = 50.85 - 23.05 * 3 / (0 + 2 + 2 + 2 + 3) = 43.17
通过比较可以得到 item2 不符合分配
item2 (0 + 200) < min(250, 300) = 250
所以 item2 的最终宽度是 250
由于 item2 如果是按分配应该是 200,现在是 250,多占据了 50
所以要重新分配空间,分配的空间中要减少相应比例的空间
item3 重新分配后的剩余空间 = 28.78 - 50 * 2 / (2 + 2 + 2 + 3) = 17.67
item4 重新分配后的剩余空间 = 28.78- 50 * 2 / (2 + 2 + 2 + 3) = 17.67
item5 重新分配后的剩余空间 = 28.78- 50 * 2 / (2 + 2 + 2 + 3) = 17.67
item6 重新分配后的剩余空间 = 43.17 - 50 * 3 / (2 + 2 + 2 + 3) = 26.5
通过比较可以得到以上的成员都符号分配
item3 的最终宽度是 17.67 + 200 = 217.67
item4 的最终宽度是 17.67 + 70= 87.67
item5 的最终宽度是 17.67 + 149.5= 167.17
item6 的最终宽度是 26.5 + 200 = 226.5
可以看到计算结果和最终的结果是一致的
以上是关于在伸长状态下成员的计算规则,那么在收缩状态下,上面的计算公式还能起作用吗
缩
下面的 flex 布局中设置了 6 个成员,每个成员都设置了不同的 width flex-basic content flex-shrink 值, 为了让元素处于收缩状态,我修改了成员的大小
<div class="wrapper"> <h1>test</h1> <style> .container {display: flex; background-color: #915151;} .item {height: 80px; text-align: center; background-color: rgb(214, 120, 52); border-radius: 1em;border: 5px solid #000;text-align: left;margin: 15px;padding: 10px} </style> <div class="container"> <div class="item" style="flex-shrink: 1;width: 100px; flex-basis: 500px"> <div style="width: 40px"></div> </div> <div class="item" style="flex-shrink: 0; width: 250px; flex-basis: 300px"> <div style="width: 300px"></div> </div> <div class="item" style="flex-shrink: 2; flex-basis: 500px"> <div></div> </div> <div class="item" style="flex-shrink: 2; width: 400px"> <div></div> </div> <div class="item" style="flex-shrink: 2;"> <div style="font-family: monospace;">12345678910111213141516</div> </div> <div class="item" style="flex-shrink: 3; width: 300px;"> <div style="width: 100px"></div> </div> </div> </div>复制代码
下面是生成布局的截图,包括了每个成员的尺寸
下面将通过公式计算成员最终的宽度值
按照前面提及的转化规则,得到类似下面的表格
依据上面提到的计算步骤进行计算
获取剩余空间
剩余空间 = 容器可分配空间 - 每个成员(margin + border + padding + t-flex-basis)的和
在我这里的容器宽度是 1349px,这个也是这里的容器可分配空间
剩余空间 = 1349 - (30 + 10 + 20 + 500) - (30 + 10 + 20 + 300) - (30 + 10 + 20 + 500) - (30 + 10 + 20+ 400) - (30 + 10 + 20 + 149.5) - (30 + 10 + 20 + 300) = -1160.5
分配剩余空间
分配的剩余空间 = 剩余空间 * (当前成员的 flex-shrink) / 待分配成员的 flex-shrink值之和
item1 分配的剩余空间 = -1160.5 * 1 / (1 + 0 + 2 + 2 + 2 + 3) = -116.05
item2 分配的剩余空间 = -1160.5 * 0 / (1 + 0 + 2 + 2 + 2 + 3) = 0
item3 分配的剩余空间 = -1160.5 * 2 / (1 + 0 + 2 + 2 + 2 + 3) = -232.1
item4 分配的剩余空间 = -1160.5 * 2 / (1 + 0 + 2 + 2 + 2 + 3) = -232.1
item5 分配的剩余空间 = -1160.5 * 2 / (1 + 0 + 2 + 2 + 2 + 3) = -232.1
item6 分配的剩余空间 = -1160.5 * 3 / (1 + 0 + 2 + 2 + 2 + 3) = -348.15
找出不符合分配的成员,重新计算分配空间
所谓不符合分配的成员指的是 (分配的剩余空间 + t-flex-basis) < min(t-content, t-width)
当成员不符合分配时,那么该成员的最终值就是 t-content 和 t-width 中的最小值
否则成员的最终值就是:分配的剩余空间 + t-flex-basis
通过比较可以得到 item5 不符合分配
item5 (-232.1 + 149.5) < min(t-content,t-width) = 149.5
所以 item5 的最终宽度是 149.5
由于 item5 如果是按分配应该是 -82.6,现在是 149.5,多占据了 232.1
所以要重新分配空间,分配的空间中要减少相应比例的空间
item1 重新分配后的剩余空间 = -116.05 - 232.1 * 1 / (1 + 0 + 2 + 2 + 3) = -145.0625
item2 重新分配后的剩余空间 = 0 - 232.1 * 0 / (1 + 0 + 2 + 2 + 3) = 0
item3 重新分配后的剩余空间 = -232.1 - 232.1 * 2 / (1 + 0 + 2 + 2 + 3) = -290.125
item4 重新分配后的剩余空间 = -232.1 - 232.1 * 2 / (1 + 0 + 2 + 2 + 3) = -290.125
item6 重新分配后的剩余空间 = -348.15 - 232.1 * 3 / (1 + 0 + 2 + 2 + 3) = -435.1875
通过比较可以得到 item6 不符合分配
item6 (-435.1875 + 300) < min(300, 100) = 100
所以 item6 的最终宽度是 100
由于 item6 如果是按分配应该是 -135.1875,现在是 100,多占据了 235.1875
所以要重新分配空间,分配的空间中要减少相应比例的空间
item1 重新分配后的剩余空间 = -145.0625 - 235.1875 * 1 / (1 + 0 + 2 + 2) = -192.1
item2 重新分配后的剩余空间 = 0 - 235.1875 * 0 / (1 + 0 + 2 + 2) = 0
item3 重新分配后的剩余空间 = -290.125- 235.1875 * 2 / (1 + 0 + 2 + 2) = -384.2
item4 重新分配后的剩余空间 = -435.1875 - 235.1875 * 2 / (1 + 0 + 2 + 2) = -529.2625
通过比较可以得到 item4 不符合分配
item4 (-529.2625 + 400) < min(t-content,t-width) = 0
所以 item4 的最终宽度是 0
但是可以看到 item4 实际的渲染结果不是 0,所以以上的计算公式在收缩状态下是无效的,问题出现在计算剩余空间的计算上,在收缩状态下的计算公式是
分配的剩余空间 = 剩余空间 * (当前成员的 flex-shrink * t-flex-basis) / 待分配成员的(flex-shrink * t-flex-basis)之和
重新计算以上的步骤
分配剩余空间
分配的剩余空间 = 剩余空间 * (当前成员的 flex-shrink * t-flex-basis) / 待分配成员的(flex-shrink * t-flex-basis)之和
item1 分配的剩余空间 = -1160.5 * 1 * 500 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 2 * 149.5 + 3 * 300) = -165.83
item2 分配的剩余空间 = -1160.5 * 0 * 300 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 2 * 149.5 + 3 * 300) = 0
item3 分配的剩余空间 = -1160.5 * 2 * 500 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 2 * 149.5 + 3 * 300) = -331.666
item4 分配的剩余空间 = -1160.5 * 2 * 400 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 2 * 149.5 + 3 * 300) = -265.33
item5 分配的剩余空间 = -1160.5 * 2 * 149.5 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 2 * 149.5 + 3 * 300) = -99.168
item6 分配的剩余空间 = -1160.5 * 3 * 300 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 2 * 149.5 + 3 * 300) = -298.5
找出不符合分配的成员,重新计算分配空间
所谓不符合分配的成员指的是 (分配的剩余空间 + t-flex-basis) < min(t-content, t-width)
当成员不符合分配时,那么该成员的最终值就是 t-content 和 t-width 中的最小值
否则成员的最终值就是:分配的剩余空间 + t-flex-basis
通过比较可以得到 item5 不符合分配
item5 (-99.168 + 149.5) < min(t-content,t-width) = 149.5
所以 item5 的最终宽度是 149.5
由于 item5 如果是按分配应该是 50.33,现在是 149.5,多占据了 99.17
所以要重新分配空间,分配的空间中要减少相应比例的空间
item1 分配的剩余空间 = -165.83 - 99.17 * 1 * 500 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 3 * 300) = -181.325
item2 分配的剩余空间 = 0 - 99.17 * 0 * 300 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 3 * 300) = 0
item3 分配的剩余空间 = -331.666 - 99.17* 2 * 500 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 3 * 300) = -362.65
item4 分配的剩余空间 = -265.33 - 99.17 * 2 * 400 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 3 * 300) = -290.1225
item6 分配的剩余空间 = -298.5 - 99.17 * 3 * 300 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400 + 3 * 300) = -326.39
通过比较可以得到 item6 不符合分配
item6 (-326.39 + 300) < min(300, 100) = 100
所以 item6 的最终宽度是 100
由于 item6 如果是按分配应该是 -26.39,现在是 100,多占据了 126.39
所以要重新分配空间,分配的空间中要减少相应比例的空间
item1 分配的剩余空间 = -181.325 - 126.39 * 1 * 500 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400) = -208.8
item2 分配的剩余空间 = 0 - 126.39 * 0 * 300 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400) = 0
item3 分配的剩余空间 = -362.65 - 126.39* 2 * 500 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400) = -417.6
item4 分配的剩余空间 = -290.1225 - 126.39 * 2 * 400 / (1 * 500 + 0 * 300 + 2 * 500 + 2 * 400) = -334.08
通过比较可以得到以上成员都符号要求
item1 的最终宽度是 500 - 208.8 = 291.2
item2 的最终宽度是 0 + 300= 300
item3 的最终宽度是 -417.6 + 500= 82.4
item4 的最终宽度是 -334.08 + 400 = 65.9
可以看到计算结果和最终的结果是一致的
总结
从以上的分析和计算中,可以看到成员的宽度受多个参数所控制,主要属性是 flex-basis, 其中在伸长和收缩状态中,计算分配的剩余空间的公式是不同的,而且在计算中还会受到成员内容大小和成员自身大小的影响,成员的最终值不得小于成员内容大小和成员自身大小中的最小值,否则就取这个最小值并重新分配剩余空间。这里可以举一个例子,很多时候我们设置 flex: 1 并希望成员都是等分的,一般情况下是没有问题的。其中 flex: 1 实际上是 flex-basis: 0%, flex-grow: 1, flex-shrink: 1,如果你不能控制成员的内容大小,当这个内容尺寸大于等分尺寸时,由于没有设置 width 值, width 值默认等于内容大小,按照以上的分析,该尺寸就会改变成员宽度,造成等分的效果失效,要避免这种情况,可以设置 width 的值为 0,这样成员内容大小和成员自身大小中的最小值就为0,等分尺寸肯定大于该值,成员尺寸便取等分尺寸,当然这个时候成员内容就会溢出。
通过以上的分析,我们对计算成员宽度已经有初步的了解,基本上能应对大部分的情况,但是 flex 布局还不止以上的属性,而且不同的属性之间还能互相组合,甚至在有的时候可能在容器上设置了绝对定位(flex功能不会消失),或者成员上设置了 box-sizing(设置的 width 值可能不同于读取的 width 值),或者 width 值是百分比(父元素宽度不确定时,width 的表现像 auto,等父元素确定后才开始计算),flex-grow 或者 flex-shrink 是小数(满足特定情况计算规则会改变)等,在以上这些情况下计算时要考虑因素会更多。
为了研究 flex 布局规则,我特意写了一个测试页面,大家有兴趣也可以去看一下
flex 布局测试 changk99.github.io/flexbox/
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 测试图片宽度
- <input> 宽度自适应变化
- 零宽度字符:和谐?屏蔽?不存在的
- Android 自定义DialogFragment宽度控制
- html – 为什么忽略表宽度?
- 超过制定宽度(或行数)显示...(或省略)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
图解CIO工作指南(第4版)
[日] 野村综合研究所系统咨询事业本部 / 周自恒 / 人民邮电出版社 / 2014-3 / 39.00
《图解CIO工作指南(第4版)》是一本实务手册,系统介绍了企业运用IT手段提高竞争力所必需的管理方法和实践经验,主要面向CEO或CIO等企业管理人士。 《图解CIO工作指南(第4版)》分为三个部分。第1部分的主题为IT管理,着重阐述运用IT技术提高企业竞争力所必需的所有管理业务,具体包括制定作为企业方针的IT战略,以及统筹执行该战略时与IT相关的人力、物力、财力、风险等要素在内的一系列管理业......一起来看看 《图解CIO工作指南(第4版)》 这本书的介绍吧!