Flex布局的那些事儿
弹性盒子布局
弹性盒子布局(Flexbox)是一种一维的布局模型,一次只能处理一个维度的布局,一行或一列。
在元素的样式上设置display: flex;
或者display: inline-flex;
可以将该元素变成 Flex container(弹性容器) 。弹性容器的直系子元素被称为 Flex item(弹性项目) ,弹性容器直接包含的 文本元素 会被包裹成匿名的弹性单元。
主轴(main axis)与交叉轴(cross axis)
主轴与交叉轴始终是相互垂直的关系。
flex-direction
主轴可以通过flex-direction
来定义,可以值4个值(默认值是row):
- row
- row-reverse
- column
- column-reverse
主轴被定义时,交叉轴也会被定义。主轴与交叉轴的位置关系可以看下图:
(start与end的位置会由writing-mode来定义,上图默认为:从左到右)
示例:
css
.container {
display: flex;
position: relative;
float: left;
width: 200px;
height: 200px;
margin: 10px;
border: 1px solid #ddd;
}
.container1 {
flex-direction: row;
}
.container2 {
flex-direction: row-reverse;
}
.container3 {
flex-direction: column;
}
.container4 {
flex-direction: column-reverse;
}
.item {
width: 50px;
height: 50px;
border: 1px solid #f00;
box-sizing: border-box;
}
html
<div class="container container1">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
<div class="container2">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
<div class="container3">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
<div class="container4">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
从上面的图片可以看出,Flex Item元素是从主轴的start位置到end位置依序排列。
多行分布:flex-wrap
css
.container {
display: flex;
width: 200px;
height: 200px;
padding: 10px;
border: 1px solid #ddd;
}
.item {
width: 80px;
height: 80px;
border: 1px solid #f00;
}
html
<div class="container">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
从上面的例子可以看出,在默认的情况下,Flex Item元素会分布在一行。
如果需要多行的分布,则需要设置Flex Container的flex-wrap
属性,可以取3个值(默认值为nowrap)。
- nowrap
- wrap
- wrap-reverse
当设置flex-wrap: wrap;
时,溢出的Flex Item元素会沿着交叉轴从start到end依序排列。flex-wrap: wrap-reverse
则从end到start依序排列。
css
.container {
display: flex;
flex-direction: row;
width: 200px;
height: 200px;
padding: 10px;
border: 1px solid #ddd;
}
.container1 {
flex-wrap: wrap;
}
.container2 {
flex-wrap: wrap-reverse;
}
.item {
width: 80px;
height: 80px;
border: 1px solid #f00;
}
html
<div class="container container1">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
<div class="container container2">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
flex-flow
flex-flow
是flex-direction
与flex-wrap
的简写形式。
css
.container {
display: flex;
flex-flow: row wrap;
}
/* 相当于 */
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
对齐方式
justify-content
justify-content
定义了在主轴上如何分配Flex Item元素及其周围的空间。常用取值如下:
- flex-start
- flex-end
- center
- space-between
- space-around
justify-content
还可取以下值:
- start
- end
- left
- right
- baseline
- first baseline
- last baseline
- space-evenly
- strecth
- safe center
- unsafe center
align-items
align-items
定义了在交叉轴如何分配Flex Item元素及其周围的空间。常用取值如下:
- stretch
- center
- start
- end
当设置为stretch
时,Flex Item元素的高度或宽度会被拉伸。
align-items
还可取以下值:
- start
- end
- left
- right
- self-start
- self-end
- first baseline
- last baseline
- safe
- unsafe
align-content
设置了浏览器如何沿着Flex Container的纵轴和网格容器(Grid Container)的主轴在内容项之间和周围分配空间。该属性对单行弹性盒子模型无效。(即:带有flex-wrap: nowrap)
align-self
会对齐当前flex行中的Flex Item元素,并覆盖 align-items
的值. 如果任何Flex Item元素的交叉轴方向margin
值设置为auto,则会忽略align-self
。
place-content
align-content
与justify-content
的简写。
间隙 gap
row-gap
row-gap
定义Flex Item的行间隙
css
.item {
row-gap: 10px;
}
column-gap
column-gap
定义Flex Item的列间隙
css
.item {
column-gap: 20px;
}
gap
row-gap
与column-gap
的简写。
css
.item {
gap: 10px 20px;
}
大小
flex-grow
flex-grow
定义了Flex Item元素的拉伸因子,值越大,占据的区域越大。
css
.container {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px 10px;
width: 200px;
height: 200px;
margin: 10px;
border: 1px solid #000;
}
.item {
height: 50px;
border: 1px solid #f00;
}
.item1 {
flex-grow: 1;
}
.item2 {
flex-grow: 2;
}
.item3 {
flex-grow: 3;
}
html
<div class="container">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
flex-shrink
flex-shrink
定义了Flex Item元素的收缩规则。Flex Item元素仅在默认宽度之和大于Flex Container的时候才会收缩。值越大,占据的区域越小。
css
.container {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px 10px;
width: 200px;
height: 200px;
margin: 10px;
border: 1px solid #000;
}
.item {
width: 80px;
height: 50px;
border: 1px solid #f00;
}
.item1 {
flex-shrink: 1;
}
.item2 {
flex-shrink: 2;
}
.item3 {
flex-shrink: 3;
}
html
<div class="container">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
</div>
flex-basis
flex-basis
定义了Flex Item元素在主轴方向的初始大小。一般情况下这个属性使用flex-basis: auto;
即可。
flex
flex-grow
、flex-shrink
与flex-basis
的简写。
可取如下值:
- initial:重置为初始值,相当于:
flex: 0 1 auto;
- auto:相当于:
flex: 1 1 auto;
- none:相当于:
flex: 0 0 auto;
- <number>
flex
属性可以指定1个、2个或3个值。
单值:值必须为以下之一:
- 一个<number>,它会被当作
flex-grow
的值; - 一个有效的宽度值(30px),它会被当作
flex-basis
的值; - 关键字initial、auto或none。
双值:第一个值必须为<number>,并且会被当作flex-grow
的值;第二个值必须是以下之一:
- 一个<number>,它会被当作
flex-shrink
的值; - 一个有效的宽度值(30px),它会被当作
flex-basis
的值。
三值:
- 第一个值必须为<number>,它会被当作
flex-grow
的值; - 第二个值必须为<number>,它会被当作
flex-shrink
的值; - 第三个必须为一个有效的宽度值(30px)或者auto,它会被当作
flex-basis
的值。
排序 order
order
定义了Flex Item的排序规则。仅对视觉顺序产生作用,并不会影响元素本身的逻辑。值小,则排前;值大,则排后。
不影响弹性盒子的属性
由于弹性盒子使用了不同的布局算法,某些属性用在弹性容器上没有意义:
- 多栏布局模块的 column-* 属性对弹性项目无效。
- float 与 clear 对弹性项目无效。使用 float 将使元素的 display 属性计为block。
- vertical-align 对弹性项目的对齐无效。