flex 布局简说
文章目录
最近同事开分享会讲到了一点 flex 布局相关的东西,但是讲得很仓促,于是决定私下里整理一下,也算是对 flex 知识的总结。内容基本参考了 MDN 还有 W3C 文档的内容,当然,并不是面向初学者的内容,是知识整合。
flex 布局的盒子模型与术语
当我们设置 display: flex
或 display: inline-flex
时,我们就生成了一个 flex 容器。 flex 容器的子元素称之为 flex item ,并且子元素使用 flex 布局。我们来看一下 flex 容器的盒子模型。
我们来规定一下这些术语:
- main axis/主轴:就是 flex 容器的方向,由
flex-direction
决定。可以取四个值:row
、row-reverse
、column
、column-reverse
。 - main size/主尺寸:就是 flex 容器的大小,由容器的宽高或 item 的宽高决定。
- cross axis/交叉轴:垂直于主轴的轴线,如果主轴是水平的,交叉轴就是垂直的,反之亦然。
- cross size/交叉尺寸:与主尺寸相对,当主尺寸为容器的宽时,交叉尺寸则为高,反之亦然。
- main start/main end/cross start/cross end/起始线/终止线:代表 flex 容器布局开始和结束的地方, flex 布局不会随着书写系统的改变而改变。
理解盒子模型是我们理解 flex 布局最关键的一步。
flex-direction
和 flex-wrap
flex-direction
定义了 flex 容器的布局方向,它的四个方向分别对应:
row
,从左到右。row-reverse
,从右到左。column
,从上到下。column-reverse
,从下到上。
flex-wrap
定义了当 flex item 溢出时应该如何处理,默认为 nowrap
,即不折行直接溢出,也可以使用 wrap
折行处理。
CSS 还提供了简写 flex-flow
用来同时设置 flex-direction
和 flex-wrap
。
flex-grow
、flex-shrink
、 flex-basis
—— flex item 的属性
flex
属性是对 flex-grow
、flex-shrink
和 flex-basis
三个属性的一个快速书写。
想要熟练使用 flex
属性,就必须要弄懂 flex-grow
、flex-shrink
和 flex-basis
。
事实上,这三个属性分别对应了 flex 布局所要做的伸长、缩短和初始长度三件事。
flex-grow
即伸长。
flex-grow
生效于当 flex 容器主尺寸大于各个 flex item 尺寸之和时,默认值为 0 。当 flex 容器主尺寸大于各个 flex item 尺寸之和时,浏览器会将剩余空间按照各个 flex item 的 flex-grow
设定分配给各个 flex item 。例如,当 flex 容器有 3 个子元素,若 3 个子元素的 flex-grow
都设定为 1 时,那么浏览器就会将剩下的空间按照 1:1:1 比例进行分配,追加到子元素后面。
flex-shrink
即缩短。
flex-shrink
生效于当 flex 容器主尺寸小于各个 flex item 尺寸之和时,默认值为 0 。当 flex 容器主尺寸小于各个 flex item 尺寸之和时,浏览器会按照子元素 flex-shrink
设定进行分配缩放。例如,当 flex 容器有 3 个子元素,若 flex 容器为 100px ,子元素的 flex-shrink
分别设定为 A 、B 元素 1 ,C 元素 2 ,三个元素宽度都为 60px ,3*60=180px
,溢出容器 80px 。我们计算总权重为 1*60+1*60+2*60=240
,因此 A 、B 元素需要减少 1*60/240*80=20px
,C 元素需要减少 2*60/240*80=40px
,最终 A 、B 为 40px ,C 为 20px 。
关于 flex-shrink
和 flex-grow
的具体计算还请参看这篇文章 。
flex-basis
即初始长度。
flex-basis
设定了 flex item 在主轴方向上初始大小,默认为 auto
,即与 flex item 自己的大小相同。当一个元素同时被设置了 flex-basis
(除值为 auto
外) 和 width
(或者在 flex-direction: column
情况下设置了height
) , flex-basis
具有更高的优先级。
flex
简写
flex
形式允许你把三个数值按这个顺序速写 —— flex-grow
,flex-shrink
,flex-basis
。
我们可以使用一个,两个或三个值来指定 flex
属性。
简写形式如下:
/* 关键字值 */
flex: auto; /* flex: 1 1 auto */
flex: initial; /* flex: 0 1 auto */
flex: none; /* flex: 0 0 auto */
/* 一个值, 无单位数字: flex-grow */
flex: 2;
/* 一个值, width/height: flex-basis */
flex: 10em;
flex: 30px;
flex: min-content;
/* 两个值: flex-grow | flex-basis */
flex: 1 30px;
/* 两个值: flex-grow | flex-shrink */
flex: 2 2;
/* 三个值: flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;
/*全局属性值 */
flex: inherit;
flex: initial;
flex: unset;
语法规则如下:
单值语法: 值必须为以下其中之一:
- 一个无单位数: 它会被当作
flex:<number> 1 0
;<flex-shrink>
的值被假定为1,然后<flex-basis>
的值被假定为0
。 - 一个有效的宽度值: 它会被当作
<flex-basis>
的值 - 关键字
none
,auto
或initial
.
双值语法: 第一个值必须为一个无单位数,并且它会被当作 <flex-grow>
的值。第二个值必须为以下之一:
- 一个无单位数:它会被当作
<flex-shrink>
的值。 - 一个有效的宽度值: 它会被当作
<flex-basis>
的值。
三值语法:
- 第一个值必须为一个无单位数,并且它会被当作
<flex-grow>
的值。 - 第二个值必须为一个无单位数,并且它会被当作
<flex-shrink>
的值。 - 第三个值必须为一个有效的宽度值, 并且它会被当作
<flex-basis>
的值。
所以我们常用的 flex: 1
其实是 flex: 1 1 0
。
aligin-items
和 justify-content
这两个属性是老朋友了。
aligin-items
是设定在交叉轴对齐的方式,默认是 stretch
,这就是为什么flex元素会默认被拉伸到最高元素的高度。
justify-content
属性用来使元素在主轴方向上对齐,主轴方向是通过 flex-direction
设置的方向。初始值是flex-start
,元素从容器的起始线排列。但是你也可以把值设置为flex-end
,从终止线开始排列,或者center
,在中间排列。
最后,关于 flex
属性的话也可以参考这篇博文: https://www.zhangxinxu.com/wordpress/2020/10/css-flex-0-1-none/ 。
文章作者 bigshans
上次更新 2023-01-10