0 概述
Flex布局,这个布局学了很久了,每次都是学了又忘,学了又忘,这次要决心把它学起来
Flex布局的关键知识点在于:
- 父flex的,主轴方向,环绕,整体排列,辅轴方向的元素对齐,整体对齐
- 子flex的,个体排序,宽度,剩余宽度伸展分配,超出宽度缩减分配,次轴方向的个体对齐
1 父flex
代码在这里
1.1 主轴方向,flex-direction
<style>
.flex1{
display: flex;
flex-direction: row;
}.flex2{
display: flex;
flex-direction: column;
}</style>
<div class="flexBox">
<h1>flex-direction:row direction</h1>
<div class="flex1">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
<h1>flex-direction:column direction</h1>
<div class="flex2">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
</div>
使用flex-direction来设置主轴方向,是横放,还是竖放。flex-direction还有个row-reverse和column-reverse,就是行列不变,只是元素反过来存放而已。
这个简单,没啥好说的
1.2 主轴环绕,flex-wrap
<style>
.flex3{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}.flex4{
display: flex;
flex-direction: row;
flex-wrap: wrap;
}</style>
<div class="flexBox">
<h1>flex-wrap:no wrap</h1>
<div class="flex3">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
<h1>flex-wrap:wrap</h1>
<div class="flex4">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
</div>
默认的flex-wrap为no-wrap,就是不环绕
这个也简单
1.3 主轴间隙,gap
<style>
.flex21{
display: flex;
gap:10px;
flex-wrap: wrap;
}.flex22{
display: flex;
column-gap:20px;
flex-wrap: wrap;
}.flex23{
display: flex;
row-gap:30px;
flex-wrap: wrap;
}</style>
<div class="flexBox">
<h1>flex-direction:gap 10</h1>
<div class="flex21">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
<h1>flex-direction:column gap 20</h1>
<div class="flex22">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
<h1>flex-direction:row gap 30</h1>
<div class="flex23">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
</div>
间隙描述的是主轴,以及环绕时候的间隙。默认的gap是0,同时表达了row-gap与column-gap。而column-gap是水平方向的间隙,row-gap是垂直方向的间隙
这点也是很直观的
注意,这个gap属性在IE下是不能正常运行的,需要在各个子控件中加入margin属性。如果你是用React的话,不妨改用Antd的Space控件来代替,它可以实现不同浏览器上的兼容性。
1.4 主轴排列,justify-content
<style>
.flex5{
display: flex;
flex-direction: row;
justify-content: flex-start;
}.flex6{
display: flex;
flex-direction: row;
justify-content: flex-end;
}.flex7{
display: flex;
flex-direction: row;
justify-content: center;
}.flex8{
display: flex;
flex-direction: row;
justify-content: space-between;
}.flex9{
display: flex;
flex-direction: row;
justify-content: space-around;
}</style>
<div class="flexBox">
<h1>justify-content:flex-start</h1>
<div class="flex5">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
<h1>justify-content:flex-end</h1>
<div class="flex6">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
<h1>justify-content:center</h1>
<div class="flex7">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
<h1>justify-content:space-between</h1>
<div class="flex8">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
<h1>justify-content:space-around</h1>
<div class="flex9">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent">c</div>
</div>
</div>
这里就开始有点混乱了,justify-content描述的是,在主轴方向,内容整体如何排列,包括:
- 整体靠左(flex-start),默认值
- 靠右(flex-end)
- 中间(center)
- 中间有空隙均匀排列(space-between)
- 两侧有空隙均匀排列(space-around)
justify-content描述的是,主轴方向(justify),内容整体(content)如何排列
1.5 辅轴元素对齐,align-items
<style>
.flex10{
display: flex;
flex-direction: row;
align-items: flex-start;
}.flex11{
display: flex;
flex-direction: row;
align-items: flex-end;
}.flex12{
display: flex;
flex-direction: row;
align-items: center;
}.flex13{
display: flex;
flex-direction: row;
align-items: baseline;
}.flex14{
display: flex;
flex-direction: row;
align-items: stretch;
}.flexAlignItems .rent,
.flexAlignItems .rent2,
.flexAlignItems .rent3,
.flexAlignItems .rent4{
height:auto;
}</style>
<div class="flexBox flexAlignItems">
<h1>align-items:flex-start</h1>
<div class="flex10">
<div class="rent">a</div>
<div class="rent2">b</div>
<div class="rent3">c</div>
<div class="rent4">d</div>
</div>
<h1>align-items:flex-end</h1>
<div class="flex11">
<div class="rent">a</div>
<div class="rent2">b</div>
<div class="rent3">c</div>
<div class="rent4">d</div>
</div>
<h1>align-items:center</h1>
<div class="flex12">
<div class="rent">a</div>
<div class="rent2">b</div>
<div class="rent3">c</div>
<div class="rent4">d</div>
</div>
<h1>align-items:baseline</h1>
<div class="flex13">
<div class="rent">a</div>
<div class="rent2">b</div>
<div class="rent3">c</div>
<div class="rent4">d</div>
</div>
<h1>align-items:stretch</h1>
<div class="flex14">
<div class="rent">a</div>
<div class="rent2">b</div>
<div class="rent3">c</div>
<div class="rent4">d</div>
</div>
</div>
当元素在主轴排列以后,它在副轴就就可以选择,元素之间在副轴的对齐,包括:
- flex-start,元素的头部在副轴方向对齐
- flex-end,元素的尾部在副轴方向对齐
- center,元素的中间在副轴方向对齐
- baseline,元素的基线在副轴方向对齐
- stretch,元素在副轴方向拉伸对齐,仅当元素在副轴的没有设置大小时,默认值
align-items,描述的是在副轴方向(align),各个元素(items)之间拿什么进行对齐
1.6 辅轴整体对齐,align-content
<style>
.flex15{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
height:500px;
}.flex16{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-end;
height:500px;
}.flex17{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: center;
height:500px;
}.flex18{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: stretch;
height:500px;
}.flex19{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: space-between;
height:500px;
}.flex20{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: space-around;
height:500px;
}</style>
<div class="flexBox">
<h1>align-content:flex-start</h1>
<div class="flex15">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
<h1>align-content:flex-end</h1>
<div class="flex16">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
<h1>align-content:center</h1>
<div class="flex17">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
<h1>align-content:stretch</h1>
<div class="flex18">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
<h1>align-content:space-between</h1>
<div class="flex19">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
<h1>align-content:space-around</h1>
<div class="flex20">
<div class="bigRent">a</div>
<div class="bigRent">b</div>
<div class="bigRent">c</div>
<div class="bigRent">d</div>
<div class="bigRent">e</div>
<div class="bigRent">f</div>
<div class="bigRent">g</div>
<div class="bigRent">h</div>
<div class="bigRent">i</div>
</div>
</div>
副轴整体对齐,是指在副轴方向上,内容整体如何对齐,包括:
- flex-start,内容整体在副轴方向的头部对齐
- flex-end,内容整体在副轴方向的尾部对齐
- center,内容整体在副轴方向的中央对齐
- stretch,内容整体在副轴方向顺序wrap对齐
- space-between,内容整体在副轴方向的中间有空隙均匀排列
- space-around,内容整体在副轴方向的两侧有空隙均匀排列
align-content,描述的是在副轴方向(align)上,内容整体(content)如何对齐
1.7 父flex盒子,dispaly
<style>
.flex1{
display:inline-flex;
}.flex2{
display:flex;
}</style>
可以设置为inline或者block方式的flex,这点与block与inline-block的区别是一样的,就没啥好说的了
1.8 语法糖,flex-flow
<style>
.flex{
flex-flow:row nowrap;
}</style>
flex-flow就是flex-direction,与flex-wrap的组合而已,这点也没啥好说的
2 子flex
代码在这里
2.1 顺序,order
<style>
.flexBox{
margin-top:30px;
border-bottom:1px solid black;
}.flex{
display: flex;
flex-direction: row;
width:100%;
}</style>
<div class="flexBox">
<h1>order</h1>
<div class="flex">
<div class="rent" style="order:2">a</div>
<div class="rent" style="order:1">b</div>
<div class="rent" style="order:3">c</div>
</div>
</div>
order也很好理解,就是强行指定渲染的顺序,而不是以DOM的出现来分主次
这个还是比较直观的
2.2 主轴大小,flex-basis
<div class="flexBox">
<h1>flex-basis</h1>
<div class="flex">
<div class="rent" style="flex-basis:100px">a</div>
<div class="rent" style="flex-basis:200px">b</div>
<div class="rent" style="flex-basis:400px">c</div>
</div>
</div>
flex-basis,可以用百分比,也可以用像素,它描述的是主轴方向的大小。在row方向的时候,我们也可以用width来描述节点的大小呀,为什么要用flex-basis。因为flex-basis的优先级更高。默认值为auto。总的来说,优先级等级为:
- flex-basis,最高
- width或者height,显式在css指定它的宽或者高
- content width或者content height,内容自身的宽或者高
这点也没啥好说的,具体可以看这里
2.3 主轴剩余空间分配,flex-grow
<div class="flexBox">
<h1>flex-grow</h1>
<div class="flex">
<div class="rent" style="flex-grow:0">a</div>
<div class="rent" style="flex-grow:1">b</div>
<div class="rent" style="flex-grow:2">c</div>
</div>
</div>
当flex是row方向nowrap的时候,多个元素的大小总和依然少于父flex的宽度的时候,就会产生主轴的剩余空间分配。它的分配方法也简单,就是按照flex-grow的权重进行分配,默认的flex-grow为0,就是该元素不分配剩余空间。经过剩余空间分配以后,flex总是能保证元素的总宽度刚好为父flex的宽度
我们看到c的flex-grow为2,b的flex-grow为1,所以,c总是能比b多1倍的剩余宽度。
剩余宽度的计算公式看这里,要注意尽可能不要让权重总和少于1,会产生你意外的布局效果,会造成剩余宽度不分配的情况。
2.4 主轴缩减空间分配,flex-shrink
<style>
.rentLong{
margin:15px;
border:1px solid black;
color:red;
background: blue;
width:500px;
height:30px;
text-align:center;
line-height: 30px;
vertical-align: middle;
}</style>
<div class="flexBox">
<h1>flex-shrink</h1>
<div class="flex">
<div class="rentLong" style="flex-shrink:1">a</div>
<div class="rentLong" style="flex-shrink:2">b</div>
<div class="rentLong" style="flex-shrink:4">c</div>
</div>
</div>
每个子div的长度都是500像素,显然会超出父flex的总宽度。那么,各个子flex就需要承担等比例收缩宽度的任务,他们各自需要收缩多少,显然这也是flex-shrink的事情,他通过权重来做等比例的收缩。经过缩减空间分配以后,flex总是能保证元素的总宽度刚好为父flex的宽度
如图所示,虽然a,b,c都是500像素的宽度,但是c的flex-shrink权重最大,所以它被缩减的空间最大。
缩减宽度的计算公式看这里,要注意尽可能不要让权重总和少于1,会产生你意外的布局效果,会造成剩余宽度不分配的情况。另外,权重的计算不仅会考虑flex-shrink,也会考虑width自身,这是因为我们尽量避免原来大width的组件收缩的程度太大。如果对所有组件的flex-shrink设置为1,那么flex布局就会根据原来组件自身的width尽可能等比例的收缩。
2.5 副轴元素对齐,align-self
<div class="flexBox">
<h1>align-self</h1>
<div class="flex2">
<div class="rent">a</div>
<div class="rent">b</div>
<div class="rent" style="align-self: flex-end;">c</div>
</div>
</div>
align-self其实就是父flex的align-items的各自特别版本而已,这个也没啥好说的
align-self的可能取值与align-items的是一致的
2.6 语法糖,flex
<style>
.flex{
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}</style>
flex其实是flex-grow,flex-shrink与flex-basis的组合语法糖而已,默认可以省略flex-shrink与flex-basis,只写flex-grow也是没问题的。
3 应用
代码在这里
3.1 管理系统布局
<style>
*{
margin:0px;
padding:0px;
}.flex{
display: flex;
flex-direction: column;
align-items: stretch;
width:100%;
height: 100vh;
}.flex .header{
height:70px;
background: blue;
}.flex .flex2{
flex:1;
display: flex;
}.flex .sidebar{
width:70px;
background: red;
}.flex .content{
flex:1;
background: pink;
}.flex .footer{
height: 70px;
background: yellow;
}</style>
<div>
<h1>flex admin</h1>
<div class="flex">
<div class="header">
header</div>
<div class="flex2">
<div class="sidebar">
sidebar</div>
<div class="content">
content</div>
</div>
<div class="footer">
footer</div>
</div>
</div>
注意一下用100vh来描述屏幕高度
3.2 等比例布局
<style>
*{
margin:0px;
padding:0px;
}.flex{
display: flex;
}.flex div{
flex-basis:25%;
text-align: center;
border:1px solid black;
}</style>
<div>
<h1>flex 25%precent</h1>
<div class="flex">
<div>a</div>
<div>b</div>
<div>c</div>
<div>d</div>
</div>
</div>
直接用flex-basis的百分比就可以了,注意,border的大小不影响flex-basis的布局,也不修改box-sizing属性,也不需要考虑空格问题,确实好用。
3.3 垂直与宽度居中
<style>
*{
margin:0px;
padding:0px;
}.center1{
display: flex;
justify-content: center;
align-items: center;
height:300px;
border:1px solid black;
}</style>
<div>
<h1> flex center</h1>
<div class="center1">
<p>123456</p>
</div>
</div>
直接用justify-content和align-items就可以了,如果有多个item,就用justify-content和align-content。比原来的方法也好用多了。
3.4 类float布局
<style>
*{
margin: 0px;
padding: 0px;
}.flex{
border:1px solid blue;
padding: 30px;
}.flex .item{
display: flex;
width: 300px;
border:1px solid black;
align-items: flex-start;
}.flex .item img{
flex:0;
width: 30px;
}.flex .item p{
flex:1;
}</style>
<div>
<h1>flex hang</h1>
<div class="flex">
<div class="item">
<img src="./icon.jpg"/>
<p>你好你好你好你好你好你好你好你好你好你好你好你好你好你好</p>
</div>
<div class="item">
<img src="./icon.jpg"/>
<p>你好你好你好你好你好你好你好你好你好你好你好你好你好你好</p>
</div>
</div>
</div>
一侧有图片,另外一侧占用剩余宽度,两者顶部对齐,也是简单的
3.5 左右浮动布局
<style>
*{
margin:0px;
padding:0px;
}.right1{
display: flex;
flex-direction: row;
}.right1 .l{
flex:0;
}.right1 .c{
flex:1;
text-align: center;
}.right1 .r{
flex: 0;
}</style>
<div>
<h1>flex right</h1>
<div class="right1">
<div class="l">left</div>
<div class="c">center</div>
<div class="r">right</div>
</div>
</div>
左右浮动,可以看成是justify-content的space-between,也可以看成是主轴三部分,中间部分占据所有的剩余宽度。
4 总结
有用且兼容性较好的布局方式,需要转换一下思维,难度并不大。参考资料
- 本文作者: fishedee
- 版权声明: 本博客所有文章均采用 CC BY-NC-SA 3.0 CN 许可协议,转载必须注明出处!