flex弹性布局

一、弹性布局概念

如果一个元素是弹性布局元素,那么它的子元素都可以认为是一个个充满弹性的弹簧。它们能自由地弹性伸缩,来填充可用空间,或将其收缩来避免溢出。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
.parent {
width: 400px;
outline: 1px dashed red;
display: flex; /*对父元素设置flex布局*/
}
.child {
flex: 1; /*子元素需要设置“弹性”*/
background-color: lightseagreen;
border: 2px solid white;
color: white;
text-align: center;
}
1
2
3
4
5
6
7
<body>
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
</div>
</body>

子元素就会撑满整个父元素:

1
2
3

基本概念

我们把设置为display:flex的元素叫做弹性容器(flex container),而它的所有子元素就自动变成了弹性项目(flex item)。其他属性也一一在图中呈现。

二、flex-container的相关属性

注意:该节内容所示属性,都是弹性容器(flex-container)的相关属性,不是弹性项目(flex-item)的

flex-direction主轴方向

flex-direction: row | row-reverse | column | column-reverse

  • row默认值,表示弹性项目(flex item)从左往右排列。
  • row-reverse:表示弹性项目(flex item)从右往左排列。
  • column:表示弹性项目(flex item)从上往下排列。
  • column-reverce:表示弹性项目(flex item)从下往上排列。

  • flex-direction只改变主轴方向,侧轴方向不变

flex-wrap 换行方式

flex-wrap:nowrap | wrap | wrap-reverse

  • nowrap默认值,不换行
  • wrap:沿着侧轴方向换行
  • no-wrap:仍是沿着侧轴方向换行,只不过侧轴方向需要逆置

    或许有人会问,为什么no-wrap不能直接解释成:逆着侧轴方向换行?原因在align-content这一节会得到解释。

flex-flow 同时设置方向和换行

flex-flow: <flex-direction> || <flex-wrap>

只是flex-directionflex-wrap的缩写,默认值是row nowrap

justify-content 主轴方向的对齐方式

justify-content:flex-start | flex-end | center | space-between | space-around

  • flex-start:默认值,向主轴起点(main start)对齐
  • flex-end:向主轴终点(main end)对齐
  • center:居中对齐
  • space-between:两端对齐
  • space-around:分布对齐(每个 item 都平分所有空隙,所以会发现,两个元素间空隙的宽度会是最左边缝隙的宽度的两倍)

align-items 侧轴方向的对齐方式

align-items:flex-start | flex-end | center | stretch | baseline

  • flex-start:与侧轴起点(cross start)对齐
  • flex-end:与侧轴终点(cross end)对齐
  • center:居中对齐
  • stretch默认值,如果弹性项目未设置高度,那么其将延伸铺满整个弹性容器
  • baseline:让弹性项目的第一行文字的基线对齐

align-content 多行在侧轴方向的对齐方式

align-content: flex-start | flex-end | center | space-between | space-around | stretch

  • flex-start:所有行都往侧轴起点(cross start)聚集
  • flex-end:所有行都往侧轴终点(cross end)聚集
  • center:居中对齐
  • space-between:两端对齐
  • space-around:分布对齐
  • stretch默认值,如果项目未设置高度,那么将延伸铺满整个容器

  • 那么,如果对弹性容器设置flex-wrap:wrap-reverse会怎么样?
    我们发现,设置为flex-start的这个例子中,两行元素聚集于下端,说明侧轴的起点在下面,正好也恰恰说明了,wrap-reverse逆置了整个侧轴,而不是对元素换行的做出规定。

三、flex-item的相关属性

order 排列顺序

order:<interger>

弹性项目会依照flex-direction设定的顺序,并按照order从小到大排列
举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.parent {
width: 400px;
background-color: #ffcc00;
padding: 10px;
display: flex;
flex-wrap: wrap;
margin: 10px;
}
.child {
width: 50px;
height: 50px;
background-color: #fd3402;
margin: 5px;
line-height: 50px;
color: white;
text-align: center;
}
1
2
3
4
5
6
7
8
9
10
11
<body>
<div class="parent">
<!--对item进行乱序-->
<div class="child" style="order:4;">4</div>
<div class="child" style="order:1;">1</div>
<div class="child" style="order:5;">5</div>
<div class="child" style="order:2;">2</div>
<div class="child" style="order:-1;">-1</div>
<div class="child" style="order:3;">3</div>
</div>
</body>

仍然会按照order顺序排列好:

flex-basis 初始宽高

flex-basis: content | <length>

  • 这个属性用来设置元素在主轴方向占据的大小
  • content默认值,基于 flex 的元素自动调整大小(也就是项目本身的大小)
  • <length>:可以设置为和widthheight一样的长度值(px, mm, pt…)或百分比,那么项目将有固定的大小。
  • 当同时设置widthflex-basis时,后者会覆盖前者

flex-grow 放大比例

flex-grow:<number&gt(非负值);

  • 当弹性容器有剩余的空间时,flex-grow会按照比例为弹性项目分配剩余空间,这也就变成了一个放大效果,而flex-grow规定的,就是放大效果。

  • 默认值是 0,下面就是默认的分配情况:

  • 当为所有弹性项目都设置flex-grow:1;之后:

  • 如果给项目 2,设置flex-grow:2;而其他项目都是 1,那么项目 2 分配到的剩余空间就会是其他项目的两倍:

  • 有一个计算公式可以计算一个项目能分配到的剩余空间(项目的宽度 = 基础宽度 + 该项目的 flex-grow 值 / 同一行或列(也就是同一主轴)所有项目的 flex-grow 值的和 * 容器的剩余宽度):
    item's length = flex-basis + flex-grow / sum(flex-grow) * remain

  • 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.parent {
width: 250px;
background-color: #ffcc00;
padding: 10px;
display: flex;
flex-wrap: wrap;
}
.child {
width: 60px;
height: 50px;
flex-grow: 1;
background-color: #fd3402;
margin: 1.25px;
line-height: 50px;
color: white;
font-family: consolas;
text-align: center;
}
1
2
3
4
5
6
7
<div class="parent">
<div class="child" style="flex-grow: 1;">flex:1;</div>
<div class="child" style="flex-grow: 2;">flex:2;</div>
<div class="child" style="flex-grow: 1;">flex:1;</div>
<div class="child" style="flex-grow: 2;">flex:1;</div>
<div class="child" style="flex-grow: 3;">flex:2;</div>
</div>

flex-shrink 缩小比例

flex-shrink:<number&gt(非负值);

  • flex-grow刚好相反,flex-shrink可以当做是用来分配剩余的负空间的。

  • 当一行弹性项目超出了弹性容器的宽度,那么这些超出的宽度就是所谓的负空间,那么flex-shrink就会和flex-grow类似,来分配这些负空间,从而让弹性项目仍旧撑满整个容器,而不溢出来。这就好比把元素缩小了。

  • flex-grow不同,flex-shrink的默认值是 1,所以不用设置flex-shrink也会有缩小效果。

  • 同样有一个计算公式可以计算一个项目能分配到的剩余负空间(项目的宽度 = 基础宽度 + 该项目的 flex-shrink 值 / 同一行或列(也就是同一主轴)所有项目的 flex-shrink 值的和 * 容器的剩余负宽度):
    item's length = flex-basis + flex-shrink / sum(flex-shrink) * remain

  • 然而,在此时,我发现了一个神奇的现象。当弹性项目的子元素,在主轴方向的尺寸,超过了该弹性项目,就会导致这个弹性项目的flex-shrink失效。当然解决方案也已经列在注释中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.parent {
width: 250px;
background-color: #ffcc00;
padding: 10px;
display: flex;
}
.child {
width: 70px;
height: 200px;
background-color: #fd3402;
margin: 5px;
font-family: consolas;
text-align: center;
/*min-width:0;*/ /*解决方案一*/
/*overflow-x: hidden;*/ /*解决方案二*/
/*word-break:break-all;*/ /*针对长文字的解决方案*/
}
1
2
3
4
5
6
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"><div style='width:200px;height:50px;background-color: white;'></div></div>
<div class="child"></div>
</div>

flex

flex: [<flex-grow> <flex-shrink>? || <flex-basis>] | none

  • flexflex-grow, flex-shrinkflex-basis的简写。
  • flex-shrinkflex-basis是可选值。
  • 默认值是:0 0 auto;

align-self 单个项目在侧轴上的对齐方式

align-self: auto | flex-start | flex-end | center | baseline | stretch;

  • 设置单个项目在侧轴上的对齐方式,会覆盖align-items
  • 默认是auto,表示继承父元素的align-items,如果没有父元素,就等同于stretch