众所周知,flex 布局是如今最常见的布局方式之一。但在我们设置单个元素的属性的时候,通常只用到flex 的一个值,或者使用若干个值,却不了解它的具体计算逻辑,只知道它会填充。这篇文章,尝试解读 flex 属性的作用和算法。
推荐:★★★☆
索引
flex属性定义
- 目前我们已知,flex 是三个属性的简写。这三个属性按顺序分别为
flex-grow
, flex-shrink
, flex-basis
. 他们的含义分别是——用我自己的理解来解释
- 父元素容器宽度富余时,分配多余的宽度的比例,单位是数字
- 父元素容器宽度不足时,分配欠缺的宽度的比例,单位是数字
- 父元素容器宽度分配的基准值,也就是最小的计算单位,数值是宽度
- 这样表达不知是否容易理解,实际这和我自己之前的理解是相悖的,之前我一直以为是按比例分配的是父元素整个容器的宽度,其实不然。不知是否有小伙伴和我一样理解有误。
flex属性分配
- flex 设置为 1 的时候。其三个元素的默认值是
1, 1, auto
.
- 可以理解为大家平分。
- 这里不多赘述,这是我们最常用的方式。
- 这篇文章主要讨论的是它们的分配逻辑,计算方式。
- 下面就用公式和实例来详细解释个中的含义。
flex算法
- 这里要注意的是,主要关注点在于区分父元素容器还有没有富余的情况。打个比方,就是你爷爷有没有留下多余的地给孩子们分,如果有,就使用
flex-grow
, flex-basis
计算,不然就使用 flex-shrink
, flex-basis
- 是的,没看错。不管在哪种情况下,实际只有两个属性是生效的,有一个属性不在计算范围之内,需要略过。
- 纳入计算的总的田地(宽度),是超出父容器的,或者少于父容器的部分。
- 那么什么时候子元素的总和会出现以上两种情况呢,因为默认 flex 布局本身是适应的。答案就是设置了 flex-basis 的情况,手动设置的 flex-basis 之和超出了父元素的宽度值。
- 下面是子元素宽度之和少于父元素的情况下(
child_width1 + child_width2 + ... < parent_width
),计算的方式。这里为了方便理解,设定是两个子元素,实际上多个子元素的算法也是完全一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const extra_all_width = parent_width - (flex_basis1 + flex_basis2);
const basic_width1 = flex_grow1 * flex_basis1; const basic_width2 = flex_grow2 * flex_basis2;
const all_width = basic_width1 + basic_width2;
const extra_width1 = (basic_width1) / all_width * extra_all_width; const extra_width2 = (basic_width2) / all_width * extra_all_width;
const width1 = flex_basis1 + extra_width1; const width2 = flex_basis2 + extra_width2;
|
- 有了以上的算法,那么就会比较容易推算出父元素宽度不足的情况下(
child_width1 + child_width2 > parent_width
)的计算方式。比例的参考值从 flex-grow
改为 flex-shrink
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const shortage_all_width = (flex_basis1 + flex_basis2) - parent_width;
const basic_width1 = flex_shrink1 * flex_basis1; const basic_width2 = flex_shrink2 * flex_basis2;
const all_width = basic_width1 + basic_width2;
const shortage_width1 = (basic_width1) / all_width * shortage_all_width; const shortage_width2 = (basic_width2) / all_width * shortage_all_width;
const width1 = flex_basis1 - shortage_width1; const width2 = flex_basis2 - shortage_width2;
|
flex实践
- 有了以上的算法,那么来计算宽度就轻而易举了。
- 这里罗列了设定了父元素宽度,且有两个子元素的情况。分别是宽度超出和不足的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; } .container { width: 600px; height: 300px; display: flex; } .left { flex: 1 2 500px; background: red; } .right { flex: 2 1 400px; background: blue; }
.left1 { flex: 1 2 200px; background: yellow; } .right1 { flex: 2 1 100px; background: olivedrab; } </style> </head> <body> <div class="container"> <div class="left"></div> <div class="right"></div> </div> <div class="container"> <div class="left1"></div> <div class="right1"></div> </div> </body> </html>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const shortage_all_width = (500 + 400) - 600;
const basic_width1 = 2 * 500; const basic_width2 = 1 * 400;
const all_width = 1000 + 400;
const shortage_width1 = 1000 / 1400 * 300; const shortage_width2 = 400 / 1400 * 300
const width1 = 500 - 214.28; const width2 = 400 - 82.72;
|
- 这里实践下来,相信是比较容易理解的了。那么在以上的代码里,还剩下一个宽度富余的场景,各位有兴趣可以自行计算一下子元素
left1
, right1
的宽度。
- 如果以上有计算错误或理解有误的地方,欢迎指正。
参考
评论