布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。
Flex布局是什么?
flex意为“弹性布局”,用来为盒状模型提供最大的灵活性,我们常用的pc端和移动端的适配基本上都是用flex布局解决的,如果一个元素使用了flex弹性布局(以下都会简称为:flex布局),则会在内部形成BFC
交叉与主轴
学习flex布局需要明白”主轴“与”交叉轴“的概念,采用flex布局的元素,称为”容器“ ( flex container),它的所有子元素都是容器的”项目“(flex item),容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做
main start ,结束位置叫做 main end ;交叉轴的开始位置叫做 cross start ,结束位置叫做 cross end 。
容器的属性
-
flex-direction:决定主轴的方向(即项目的排列方向)
flex-direction有四个属性值
row(默认值):主轴为水平方向,起点在左端
.main {
width: 500px;
height: 300px;
background: skyblue;
display: flex;
flex-direction: row;
}
.main div {
width: 100px;
height: 100px;
background: pink;
font-size: 20px;
}
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
row-reverse:主轴为水平方向,起点在右端
column:主轴为垂直方向,起点在上端
column-reverse:主轴为垂直方向,起点在下端
flex-wrap属性
在默认情况下,项目都排在一条线上,无论是否给定宽度,都是不会主动换行 默认属性:nowrap不换行
wrap属性:换行,第一行在上方
wrap-reverse属性:第一行在下方
flex-flow属性
是flex-direction属性和flex-wrap属性的简写形式默认值是 row nowrap
flex-flow: row nowrap;//<flex-direction>|| <flex-wrap>
justify-content属性
justify-content属性定义了项目在主轴上的对齐方式
flex-start(默认值):左对齐
flex-end:右对齐
center:居中对齐
space-around每个元素两侧的间隔相等
space-between两侧元素靠边对齐中间元素均匀对齐
space-evenly:每个项目的间隔与项目和容器之间的间隔是相等的
align-items属性
align-items属性定义项目在交叉轴上(垂直方向)如何对齐
flex-start:交叉轴(垂直方向)的起点对齐
flex-end:垂直方向底部对齐
center:垂直方向居中对齐
stretch(默认值): 如果项目未设置高度或设为auto,将占满整个容器的高度(我把height高度清空了)
align-content属性
align-content属性定义了轴线的对齐方式,
- 前提是需要对父元素设置设flex-wrap:wrap否则不会生效
- 对父元素设置自由盒属性display:flex;
- 对父元素设置align-content相关的属性
flex-start属性:交叉轴的起点对齐
flex-end属性:交叉轴的底部对齐
stretch:轴线占满整个交叉轴
order(定义在子元素身上)
order 属性定义项目的排列顺序。数值越小,排列越靠前,默认为0,可以是负数。
.main {
width: 500px;
height: 300px;
background: skyblue;
display: flex;
/* flex-direction: row;
flex-wrap: wrap-reverse; */
flex-flow: row wrap;
/* justify-content: space-evenly; */
/* align-items: stretch; */
align-content: stretch;
}
.main div {
width: 100px;
height: 100px;
background: pink;
font-size: 20px;
}
.five {
order: 1;
}
.one {
order: 2;
}
.two {
order: 3;
}
<div class="main">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
flex-grow(定义在子元素身上)
flex-grow flex容器中剩余空间的多少应该分配给项目,也称为扩展规则。最终的项目的宽度为:自身宽度 + 容器剩余空间分配宽度,flex-grow最大值是1,超过1按照1来扩展
flex-grow: <number>; /* default 0 */
flex-grow: 0.2; /* default 0 *///盒子1
flex(定义在子元素身上)
flex 属性是 flex-grow , flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto 。后两个属性可选。
flex: none | [ <'flex-grow'><'flex-shrink'>? || <'flex-basis'>]
flex-shrink
flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值,默认值是1
flex-shrink: <number>; /* default 1 */
默认情况下,第一个div宽度是200,第二个div宽度是300,两个相加应该超过父元素的400,但是由于 flex-shrink 都设置为1,将两个div都收缩在父元素中
.item {
width: 400px;
height: 300px;
background: skyblue;
display: flex;
padding: 5px;
}
.item div {
height: 100px;
font-size: 20px;
}
.item div:nth-child(1) {
flex-shrink: 1;
width: 200px;
background: pink;
}
.item div:nth-child(2) {
flex-shrink: 1;
width: 300px;
background: cadetblue;
}
那收缩后的子项宽度是怎么样计算的呢?实际上有一个公示:
(200+300)所有子项的宽度的和 -(400)容器的宽度 =(100)- 第一个子项的宽度占比:
2/5,第二个子项的宽度占比:3/5 - 则第一个子项的的宽度为:
200-2/5 * 100= 160,第二个子项的宽度为:300-3/5 * 100= 240
等高布局
每一列的内容不一样,但容器的高度时等高的
.item {
width: 400px;
height: 300px;
background: skyblue;
display: flex;
justify-content: space-between;
padding: 5px;
}
.item div {
width: 100px;
font-size: 20px;
background: pink;
}
.item div p {
text-align: center;
}
左侧宽度固定,右侧自适应布局
html,
body {
margin: 0;
padding: 0;
}
.container {
display: flex;
width: 100%;
height: 100vh;
background: skyblue;
}
.left-tree {
width: 200px;
height: 100%;
background: pink;
}
.main {
flex: 1 1 auto;
}
常见的TOB系统布局方式,左侧是菜单树,右侧是内容
黏贴性页脚
无论中间的内容有多少,页脚始终在底部展示
html,
body {
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
width: 100%;
height: 100vh;
}
.header {
width: 100%;
height: 60px;
background: pink;
}
.main {
flex: 1 1 auto;
background: skyblue;
}
.footer {
width: 100%;
height: 60px;
background: pink;
}
flex布局 实现布局效果。缺点是相较于 grid网格布局 来说, flex布局 是 一维布局 ,一般用于单行或者单列的布局,如果要实现多行多列的布局,推荐使用 gird网格布局