flex 布局详解
关于flex具体是什么在此不赘述,官方文档在此:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox
我自己通过实例总结如下:
flex 布局主要有两大块:1. 父元素;2. 子元素
把这两大块搞明白就算吃透flex布局了(接下来的实例中,我会将完整代码贴出来,大家可复制代码在浏览器运行感受一下)。
父元素
1. justify-content
元素水平方向上的布局 常用的也就5个属性而已,代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>justify-content</title>
<style>
.boxp{
background: lightgreen;
height: 100px;
display: flex;
margin-bottom: 50px;
}
.boxp div{
width: 100px;
height: 100px;
background: purple;
}
.center{
justify-content: center;
}
.space-between{
justify-content: space-between;
}
.space-around{
justify-content: space-around;
}
.flex-start{
justify-content: flex-start;
}
.flex-end{
justify-content: flex-end;
}
</style>
</head>
<body>
<!-- justify-content: center -->
<div class="boxp center">
<div></div><div></div><div></div><div></div>
</div>
<!-- justify-content: space-between -->
<div class="boxp space-between">
<div></div><div></div><div></div><div></div>
</div>
<!-- justify-content: space-around -->
<div class="boxp space-around">
<div></div><div></div><div></div><div></div>
</div>
<!-- justify-content: flex-start -->
<div class="boxp flex-start">
<div></div><div></div><div></div><div></div>
</div>
<!-- justify-content: flex-end -->
<div class="boxp flex-end">
<div></div><div></div><div></div><div></div>
</div>
</body>
</html>
效果如下:

注意
- space-between: 先是两端对齐,剩余的子元素之间间隔相同
- space-around: 每个元素左右距离相同(为了方便理解,可想象成每个元素都是margin: 0 20px; 这种效果,所以两侧的剩余宽度是项目间隔宽度的二分之一)。
2. align-items
元素垂直方向上的布局,常用的就5个属性,代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>align-items</title>
<style>
.boxp{
height: 120px;
background: lightgreen;
display: flex;
margin-bottom: 30px;
}
.boxp div{
width: 80px;
background: yellow;
margin: 0 10px;
}
.one{
height: 50px;
font-size: 12px;
}
.two{
height: 80px;
font-size: 25px;
}
.three{
height: 60px;
font-size: 45px;
}
.noheight{
height: auto;
}
.center{
align-items: center;
}
.flex-start{
align-items: flex-start;
}
.flex-end{
align-items: flex-end;
}
.baseline{
align-items: baseline;
}
.stretch{
align-items: stretch;
}
</style>
</head>
<body>
<!-- align-items: center; -->
<div class="boxp center">
<div class="one">1</div><div class="two">2</div><div class="three">3</div>
</div>
<!-- align-items: flex-start; -->
<div class="boxp flex-start">
<div class="one">1</div><div class="two">2</div><div class="three">3</div>
</div>
<!-- align-items: flex-end; -->
<div class="boxp flex-end">
<div class="one">1</div><div class="two">2</div><div class="three">3</div>
</div>
<!-- align-items: baseline; -->
<div class="boxp baseline">
<div class="one">1</div><div class="two">2</div><div class="three">3</div>
</div>
<!-- align-items: stretch; -->
<div class="boxp stretch">
<div class="noheight">1</div><div class="noheight">2</div>
</div>
</body>
</html>
效果:

注意
- baseline: 使整行文字的基准线平齐,在此基础上布局子元素
- stretch: 元素没有设置具体高度值,或者高度属性值为auto时,才会生效
3. align-content
要解释这个属性,先带大家理解一下flex
布局容器中“轴”
的概念:
flex
布局的容器中默认有两根轴:1. 水平方向的主轴;2:垂直方向的轴。
容器内的元素默认按照主轴的方向进行布局,当元素不止一行的时候,水平方向就会存在多根轴;
或者当元素按照垂直方向布局,当元素不止一列时,垂直方向就会存在多根轴。
align-content
就是对这多根轴进行布局。具体看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>align-content</title>
<style>
.boxp{
background: lightgreen;
display: flex;
margin-bottom: 20px;
height: 500px;
flex-wrap: wrap;
}
.boxp div{
width: 300px;
height: 50px;
background: yellow;
margin: 10px;
}
.center{
align-content: center;
}
.space-between{
align-content: space-between;
}
.space-around{
align-content: space-around;
}
.flex-start{
align-content: flex-start;
}
.flex-end{
align-content: flex-end;
}
</style>
</head>
<body>
<!-- align-content: center -->
<div class="boxp center">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
<!-- align-content: space-between -->
<div class="boxp space-between">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
<!-- align-content: space-between -->
<div class="boxp space-around">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
<!-- align-content: flex-start -->
<div class="boxp flex-start">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
<!-- align-content: flex-end -->
<div class="boxp flex-end">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
</body>
</html>
效果:

4. flex-wrap
子元素是否可以换行展示,常用的只有三个属性,代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-wrap</title>
<style>
.boxp{
background: lightgreen;
height: 200px;
display: flex;
margin-bottom: 30px;
}
.boxp div{
width: 100px;
height: 50px;
margin: 10px;
background: yellow;
}
.wrap{
flex-wrap: wrap;
}
.nowrap{
flex-wrap: nowrap;
}
.wrap-reverse{
flex-wrap: wrap-reverse;
}
</style>
</head>
<body>
<!-- flex-wrap: wrap; -->
<div class="boxp wrap">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
<!-- flex-wrap: nowrap; -->
<div class="boxp nowrap">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
<!-- flex-wrap: wrap-reverse; -->
<div class="boxp wrap-reverse">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div>
</div>
</body>
</html>
效果:

注意
当没有设置flex-wrap属性时,默认是不换行的,所有子元素会挤在一排。
属性值为wrap-reverse
时,是把行倒序排列,但每一行里面的元素还是原来的顺序,这样想就容易理解了。
5. flex-direction
元素排列方向,常用的四个属性,代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-direction</title>
<style>
.boxp{
background: lightgreen;
display: flex;
margin-bottom: 20px;
}
.boxp div{
width: 50px;
height: 50px;
background: yellow;
margin: 10px;
}
.row{
height: 80px;
flex-direction: row;
}
.row-reverse{
height: 80px;
flex-direction: row-reverse;
}
.column{
height: 350px;
flex-direction: column;
}
.column-reverse{
height: 350px;
flex-direction: column-reverse;
}
</style>
</head>
<body>
<!-- flex-direction: row; -->
<div class="boxp row">
<div>1</div><div>2</div><div>3</div><div>4</div>
</div>
<!-- flex-direction: row-reverse; -->
<div class="boxp row-reverse">
<div>1</div><div>2</div><div>3</div><div>4</div>
</div>
<!-- flex-direction: column; -->
<div class="boxp column">
<div>1</div><div>2</div><div>3</div><div>4</div>
</div>
<!-- flex-direction: column-reverse; -->
<div class="boxp column-reverse">
<div>1</div><div>2</div><div>3</div><div>4</div>
</div>
</body>
</html>
效果:

注意
不仅要注意元素排列顺序,还要注意相对父元素的排列方向!!!
6. flex-flow
flex-direction 和 flex-wrap 的简写,应该很好理解吧,在此不赘述,请查看官网文档。
子元素
1. order
设置当前子元素的排序位置,数字越小越往前,默认为0,可以是负数。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-wrap</title>
<style>
.boxp{
background: lightgreen;
height: 100px;
display: flex;
margin-bottom: 30px;
}
.boxp div{
width: 100px;
height: 50px;
margin: 10px;
background: yellow;
}
.NO1{
-webkit-order: 5;
-moz-order: 5;
-ms-order: 5;
-o-order: 5;
order: 5;
}
.NO-3{
-webkit-order: -3;
-moz-order: -3;
-ms-order: -3;
-o-order: -3;
order: -3;
}
.NO-2{
-webkit-order: -2;
-moz-order: -2;
-ms-order: -2;
-o-order: -2;
order: -2;
}
</style>
</head>
<body>
<!-- 无order -->
<div class="boxp">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div>
</div>
<!-- 有order -->
<div class="boxp">
<div class="NO1">1</div>
<div>2</div>
<div>3</div>
<div class="NO-2">4</div>
<div class="NO-3">5</div>
</div>
</body>
</html>
效果:

2. flex-grow
设置项目占剩余空间的份额(如果有剩余空间的话),如果为0,则不拉伸,负数无效。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-grow</title>
<style>
.boxp{
background: lightgreen;
height: 100px;
display: flex;
margin-bottom: 30px;
}
.boxp div{
width: 100px;
height: 50px;
margin: 10px;
background: yellow;
}
.grow0{
flex-grow: 0;
}
.grow-1{
flex-grow: -1;
}
.grow2{
flex-grow: 2;
}
.grow3{
flex-grow: 3;
}
</style>
</head>
<body>
<!-- 无flex-grow -->
<div class="boxp">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div>
</div>
<!-- 有flex-grow -->
<div class="boxp">
<div class="grow0">flex-grow: 0</div>
<div class="grow-1">flex-grow: -1</div>
<div>3</div>
<div class="grow2">flex-grow: 2</div>
<div class="grow3">flex-grow: 3</div>
</div>
</body>
</html>
效果:

3. flex-shrink
当空间不够时,设置子元素的缩小比例。若属性值为0
,则不缩小。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-shrink</title>
<style>
.boxp{
background: lightgreen;
height: 100px;
display: flex;
margin-bottom: 30px;
}
.boxp div{
width: 500px;
height: 50px;
outline: 1px solid green;
background: yellow;
}
.shrink0{
flex-shrink: 0;
}
.shrink1{
flex-shrink: 1;
}
.shrink2{
flex-shrink: 2;
}
.shrink3{
flex-shrink: 3;
}
.shrink4{
flex-shrink: 4;
}
</style>
</head>
<body>
<!-- 无flex-shrink -->
<div class="boxp">
<div>未设置flex-shrink</div><div>未设置flex-shrink</div><div>未设置flex-shrink</div><div>未设置flex-shrink</div><div>未设置flex-shrink</div>
</div>
<!-- 有flex-shrink -->
<div class="boxp">
<div class="shrink0">flex-shrink: 0</div>
<div class="shrink1">flex-shrink: 1</div>
<div class="shrink2">flex-shrink: 2</div>
<div class="shrink3">flex-shrink: 3</div>
<div class="shrink4">flex-shrink: 4</div>
</div>
</body>
</html>
效果:

关于flex-shrink计算规则:
- 在上例中,五个子元素,每个宽度是500px,所以总宽度是500*5=2500px
- 父元素宽度1660px,所以需要子元素们缩小2500-1660=840px
- 五个子元素
flex-shrink
属性值分别为0
、1
、2
、3
、4
,所以总共缩小的份数是0+1+2+3+4=10,每一份的宽度是 840 ÷ 10 = 84px;- 第一个子元素
flex-shrink: 0
,所占份额是0,所以不进行缩小,最终宽度是500px- 第二个子元素
flex-shrink: 1
,所占份额是1,所以缩小1份,最终宽度是500-84*1=416px- 第三个子元素
flex-shrink: 2
,所占份额是2,所以缩小2份,最终宽度是500-84*2=332px- 第四个子元素
flex-shrink: 3
,所占份额是3,所以缩小3份,最终宽度是500-84*3=248px- 第五个子元素
flex-shrink: 4
,所占份额是4,所以缩小4份,最终宽度是500-84*4=164px
注意: 如果元素设置
margin
、padding
、border
,需要把这些也算进宽度里
4. flex-basis
定义子元素在主轴方向上的初始大小。
当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级.
翻译成人话就是说:flex-basis
比 width
或height
优先级高!
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-basis</title>
<style>
.boxp{
background: lightgreen;
height: 100px;
display: flex;
margin-bottom: 30px;
}
.boxp div{
width: 500px;
height: 50px;
margin: 10px;
background: yellow;
}
.basis{
flex-basis: 300px;
}
</style>
</head>
<body>
<div class="boxp">
<div>width:500px;</div>
<div class="basis">width:500px; flex-basis: 300px;</div>
</div>
</body>
</html>
效果:

5. flex
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
6. align-self
设置当前子元素相对父元素的对齐方式,可覆盖父元素的align-items
属性。属性值和align-items
的属性值一样。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-basis</title>
<style>
.boxp{
background: lightgreen;
height: 200px;
display: flex;
margin-bottom: 30px;
align-items: center;
}
.boxp div{
width: 170px;
height: 50px;
margin: 10px;
background: yellow;
}
.align-self{
align-self: flex-end;
}
</style>
</head>
<body>
<div class="boxp">
<div></div>
<div></div>
<div></div>
<div class="align-self">align-self: flex-end;</div>
<div></div>
</div>
</body>
</html>
效果:
