flex 布局原理
flex 是 flexible box 的缩写,即为 ‘ 弹性布局 ’ ,用来为盒子模型提供最大的灵活性,任何容器后可以指定为 flex 布局
无论是块元素还是行内元素
1、当为父元素盒子设置为 flex 布局之后,子元素的 float、clear 和 vertical-align属性将失效
2、伸缩布局 = 弹性布局 = 伸缩盒布局 = 弹性盒布局 = flex布局
采用 flex 布局的元素,称为 flex 容器( flex container),简称为 “容器”。
所有的子元素自动成为容器成员,称为 flex项目(flex item),简称“项目”。子元素可以横向排列也可以纵向排列。
总结flex 布局原理:通过给父元素添加 flex 属性,来控制子盒子的位置和排列方式。
相关概念:
主轴(main axis):
伸缩容器的主轴,伸缩项目主要沿着这条轴进行排列布局,主轴不一定是水平的(主要取决于justify-content属性)
主轴起点(main start)和主轴终点(main-end)
伸缩项目放置在伸缩容器从主轴起点向主轴终点方向。
主轴尺寸(main size)
伸缩项目在主轴方向的高度和宽度主要取决于主轴的尺寸,伸缩项目主要的大小属性要么是宽度要么是高毒属性,由哪一个对着主轴方向决定。
侧轴(cross axis)
垂直于主轴的称为侧轴,方向主要取决于主轴的方向。
侧轴起点(cross-start)和侧轴终点(cross-end)
伸缩行的配置从容器的侧轴起点边开始,往侧轴终点边结束。
侧轴尺寸(main size)
伸缩项目的在侧轴方向的宽度或高度就是项目的侧轴长度,伸缩项目的侧轴长度属性是宽度或高度,由哪一个对着侧轴方向决定。
那么什么是主轴和侧轴呢?
默认的主轴方向就是 x 轴方向,水平向右
默认的侧轴方向就是 y 轴方向,水平向下
弹性容器(display)
display:flex 属性将元素设置为弹性盒子
将其 display属性值定义为 flex 或是 inline-flex 将元素变为弹性盒子(弹性容器)
flex:将对象设置为弹性伸缩盒子显示
inline-flex:将对象作为内联(行内)块级伸缩盒显示
flex 和 inline-flex 的区别:
display: flex:设置父元素弹性盒子。设置元素横向排列,子元素就不在是独占一行,父元素也会随着页面大小变化而改变尺寸。
display: inline-flex:设置父元素行内弹性盒子。父元素的宽度完全由子元素撑开,并且不会随着页面大小变化改变尺寸。
实例:
1、display: flex:设置父元素弹性盒子
div{ display:flex; }
2、display:inline-flex:设置父元素行内弹性盒子
div{ display:inline-flex; }
flex 布局父级常见属性
以下7个属性是相对于父元素设置的
1、flex-direction:设置主轴的方向
2、justify-content:设置主轴上子元素排列的方式
3、flex-warp:设置子元素是否换行
4、align-content:设置侧轴上子元素的排列方向(多行)
5、align-items:设置侧轴上子元素排列方式(单行)
6、flex-flow:复合属性,相当于同时设置了 flex-direction 和 flex-warp
7、display:将盒子设置为弹性盒子
设置在子元素上面的6个属性:
1、flex-grow:弹性子元素拉伸因子
2、flex-shrink:弹性子元素的收缩比率
3、flex-basis: 指定flex元素在主轴方向上的初始大小
4、flex:规定了弹性元素如何伸长或缩短以适应 flex容器中的可用空间
5、order:设置或检索弹性盒模型子元素出现的顺序
6、align-self:子项自己在侧轴上的排列方式
一、flex-direction 设置主轴的方向
flex-direction 属性指定内部元素是如何在 flex容器中布局的,定义主轴方向(正方向 or 反方向)
设置伸缩盒主轴的起点和终点位置,子元素依然按照从主轴起点向终点方向排列
属性值:
flex-direction 属性决定主轴的方向
注意:主轴和侧轴是会变化的,当经过 flex-direction 设置后,主轴变成了侧轴,侧轴也就变成了原来的主轴。
但是子元素是跟着主轴来排列的。
(column 柱、reverse的反转)
属性值 | 说明 |
row | 默认值,主轴横向,起点左侧终点右侧(元素从左向右排列) |
row-reverse | 主轴横向反转,起点右侧,终点左侧(元素从左向右排列) |
column | 主轴纵向,起点上方,终点下方(元素从上向下排列) |
column-reverse | 主轴纵向反转,起点下方,终点上方(元素从下向上排列) |
实例:
1、flex-driection:row;
默认值,子元素沿着主轴方向排列从左向右
2、flex-driection:row-reverse;
主轴横向反转,主轴起点在左侧,终点变为右侧,子元素从右向左排列
3、flex-driection:column;
主轴纵向,主轴起点在上方,终点在下方,子元素从上到下排列
4、flex-driection:column-reverse;
主轴纵向反转,主轴起点在下方,终点在上方,子元素从下向上排列
二、justify-content 设置子元素在主轴上的对齐方式
justify-content 属性定义了浏览器之间,如何分配沿着弹性容器的主轴的元素之间及周围空间的分配
设置主轴上面的子元素
注意:使用 justify-content 元素之前一定要先确认主轴方向 flex-direction
属性值:
属性值 | 说明 |
flex-end | 弹性子元素向主轴终点位置对齐 |
center | 弹性子元素向行中间位置对齐 |
space-around | 平均分配剩余空间,两端保留子元素与子元素之间间距大小的一半 |
space-between | 先在两边贴边,再平分剩余空间(重要) |
flex-end | 弹性子元素向主轴起点位置对齐 |
实例:
1、justify-content: flex-start;
主轴的默认方向下row,子元素 first-start 向主轴的初始位置对齐【默认情况】
.flex-container{ /* 设置元素为弹性容器 */ display:flex; border:tomato 2px solid; /* 先确认主轴的方向默认主轴 x轴 row */ flex-direction:row; /* justify-content:设置主轴上子元素的排列方式 */ justify-content:flex-start; }
2、justify-content:flex-end;
行尾位置开始排列。每行最后一个弹性元素与行尾对齐(子元素向主轴终点位置对齐),其他元素将与后一个对齐。
.flex-container{ /* 设置元素为弹性容器 */ display:flex; border:tomato 2px solid; /* justify-content:设置主轴上子元素的排列方式 */ justify-content:flex-end; }
3、justify-content:center;
子元素向中间位置对齐
4、justify-center:space-around;
(平均分配盒子剩余的空间,每个盒子都有相等的margin-right 和 margin-left)
在每行上均匀分布弹性元素。相邻元素之间距离相等。每行第一个元素到行首的距离 和每行最后一个元素到行尾的距离将会是相邻元素之间距离的一半。
5、justify-content: space-between;
每行上均匀分布弹性元素。相邻的弹性元素之间距离相同。每行第一个元素与行首对齐,每行最后一个元素与行尾对齐
四、flex-wrap 元素换行
在 flex 布局中,默认的子元素是不换行,如果容纳不下,会缩小子元素的宽度,放到父元素里面。
flex-warp 设置或检索伸缩盒对象的子元素超出父容器时是否换行
默认情况下,项目都排在一条线(又称“轴线”)上,flex-warp 属性定义,flex布局中默认是不换行的。
属性值 | 说明 |
nowarp | 默认值,当子元素溢出父元素的时候不换行 |
warp | 换行,当子元素溢出父元素的时候自动换行 |
warp-reverse | 翻转warp排列(换行默认的是从左向右从上到下,翻转之后就是从下向上) |
实例:
flex布局中,默认的子元素是不换行的。当子元素的宽度超出父元素的宽度时,子元素不会换行,而是会被压缩
1、flex-warp:nowrap;
默认值,设置子元素不换行。子元素宽度被压缩。
.flex-container{ display:flex; border:tomato 2px solid; flex-wrap:nowrap; width:600px; }
2、flex-wrap:wrap; 子元素溢出父元素的时候自动换行
3、flex-wrap:wrap-reverse;反转子元素wrap的排列
五、align-items 设置侧轴上的子元素排列方式(单行)
该属性是在控制子项在测轴(默认是y轴)上的排列方式 在子元素的为单项的时候使用。
将一整行沿着 y 轴上下轴来移动
属性值:
属性值 | 说明 |
flex-start | 元素向侧轴起点对齐 |
flex-end | 元素向侧轴终点对齐 |
center | 元素在侧轴居中。如果元素在侧轴上的高度高于其容器,在上下两个方向上溢出距离相同 |
stretch | 默认值,弹性元素被在侧轴方向拉伸到与容器相同的高度 |
baseline | 将文字对齐 |
实例:
1、align-items:flex-start;
默认值,单行整行的子元素向侧轴起点对齐(表现为向上对齐),子元素不设置宽度的时候高度默认有内容撑开。
2、align-items:flex-end;
单行整行子元素向侧轴终点对齐(向下对齐)
3、align-items:center;
单行子元素向侧轴中间对齐(垂直居中对齐),子元素不设置高度默认由内容撑开
当子元素在侧轴上高度超过父元素的。设置align-items:center;后子元素会在上下两个方向上溢出相同距离。
实现将单行弹性子元素在弹性容器中水平垂直居中
.flex-container{ display:flex; border:tomato 2px solid; /* 设置主轴居中 */ justify-content:center; /* 选择测轴居中 */ align-items:center; width:600px; height:200px; margin:100px auto;
4、align-items:stretch;
当子元素不设置高度的时候,设置stretch,弹性元素会被拉伸到和父元素相同的高度。
5、align-content:baseline,将文字基于基线对齐
六、align-content 设置侧轴上子元素的排列方式(多行)
设置了浏览器如何沿着弹性盒子布局的侧轴在内容项之间和周围分配空间。
子元素在侧轴上的排列方式并且只能用于子元素换行的情况(多行),在单行的情况下是没有效果的。
注意:该属性对单行弹性盒子无效。
使用 flex-wrap:wrap 设置弹性
属性值 | 说明 |
flex-start | 在侧轴的头部开始排列 |
flex-end | 在侧轴的尾部开始排列 |
center | 在侧周中间显示 |
space-around | 子元素在侧轴平分剩余空间 |
space-between | 子元素在侧轴先分布在两侧,在平分剩余空间 |
stretch | 设置子元素高度平分父元素高度 |
1、align-content:flex-start;
默认值,弹性子元素(多行)在侧轴头部开始排列。
默认情况下,弹性子元素不会换行,flex-wrap:wrap; 子元素换行
.flex-container{ display:flex; border:tomato 2px solid; /* 设置弹性子元素换行 */ flex-wrap:wrap; /*多行弹性子元素向侧轴头部排列 */ width:600px; height:300px; margin:100px auto; }
2、align-content:flex-end;多行子元素向侧轴终点排列
3、align-content:center;所有行向侧轴的中心填充。
4、ailgn-content:space-around
弹性子元素平分侧轴的剩余空间,相当于给每行元素设置了相同距离的margin-top 和 margin-bottom
所有行在容器中平均分布,相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的距离是相邻两行间距的一半。
5、align-content:space-between;
所有行在弹性容器中平均分布,相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的边对齐。
6、align-content:stretch;
拉伸所有航来填满剩余空间,剩余空间平均分配给每一行
七、flex-flow 简写
flex-flow 是 flex-direction 和 flex-wrap 属性的综合属性
.flex-container{ display:flex; border:tomato 2px solid; /* 设置弹性子元素换行 */ flex-wrap:wrap; /* 将主轴设置为侧轴,主轴纵向 */ flex-direction:column; }
等价于,flex-flow简写属性
.flex-container{ display:flex; border:tomato 2px solid; /* 设置弹性子元素换行 */ /* 主轴纵向*/ flex-flow: cloumn wrap; }
flex 布局子项常见的属性
flex 子项目占的份数
flex-grow 弹性盒的扩展比率
flex-shrink 设置收缩比率
flex-basisalign-self 控制子项自己在侧轴的排列方式
order 属性定义子项的排列顺序(前后顺序)
flex-grow 定义弹性子元素的拉伸因子
设置或检索弹性盒的扩展比率。根据弹性盒子元素所设置的扩展因子作为比例来分配剩余空间
属性值:
<number> :数值定义扩展比率。不允许负值
0:默认值为0,如果没有定义该属性,不参与分配剩余空间
实例(分配原则如下):
1、flex-grow:0;默认值
子元素的实际宽度= 70 + (600-350)* 0 = 70px
2、flex-grow:<number>; 定义子元素扩展比率
子元素实际宽度
= 宽度 + 剩余空间 * 2/(2+2+2+2+2)
=70 +(600-350)* 2/10
=70+50=120px
section{ width:600px; display:flex; border:tomato 2px solid; } section div{ height:70px; width:70px; flex-grow:2; border:goldenrod 1px solid; background-color: gold; }
flex-shrink 属性指定了flex子元素的收缩规则。
flex元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。flex-shrink 属性值能是一个只<number>
属性值:
<number> :负值是不允许的
1:flex-shrink 的默认值为1,如果没有显示定义该属性,将会自动按照默认值1所在因子相加之后计算比率来进行控件收缩。
实例:
1、flex-shrink:1;默认值
在默认情况下,子元素的宽度超过父元素,子元素宽度会被压缩,不会溢出父元素
原则:子元素超出的空间 = 5*70 - 300 = 50px
父元素宽度300px,每个子元素宽度70px
加权总和:(70*1)* 5 = 350
每个子元素被移除的宽度:(70*1)/350 * 50 = 10px
每个子元素最终宽度:70 - 10 = 60px
所以设置 flex-shrink:1;可以使得子元素宽度被压缩到,刚好适应父元素的宽度
2、flex-shrink:<number>; 指定子元素的收缩比例
子元素超出的空间为:160+80 - 200 = 40px
父元素 200px;子元素1为160px;子元素2为80px
加权总和:160 + 80*2 = 320
元素1被移除的空间:(160*1) /320 * 40 = 20px
子元素1的宽度:160 - 20 = 140px
子元素2移除的空间:(80*2) /320 * 40 = 20px
子元素2的宽度:80 - 20 = 60px
section{ width:200px; /* height: 100px; */ margin:100px auto; display:flex; border:tomato 2px solid; } section div:nth-child(1){ height:70px; width:160px; flex-shrink: 1; border:goldenrod 1px solid; background-color: gold; } section div:nth-child(2){ height: 70px; width:80px; flex-shrink: 2; border:goldenrod 1px solid; background-color:goldenrod; }
flex-basis :指定flex元素在主轴方向上的初始大小
设置活检索弹性盒的伸缩基准值(最大作用就是更改宽度)
如果不使用box-sizing 改变盒模型,那么这个属性就决定了 flex 元素的内容区(content-box)的大小
属性值:
auto:默认值,无特定宽度(auto取决于原有的宽度)
<length>:用长度定义宽度,不能设置负值
<percentage>:百分比定义宽度,不能设置负值
一、flex 属性
flex规定了弹性元素如何伸长或缩短以适应 flex容器中的可用空间。
这是一个简写属性,可以用来设置 flex-grow、flex-shrink、flex-basis。设置或检索伸缩盒对象的子元素如何分配空间。建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
flex用于合并指定 flex-grow 和 flex-grow 以及 flex-basis 属性,默认值为 0 1 auto。
如果缩写 flex:1,则其计算值为 :1 1 0,auto等价与1 1 auto,none等价于 0 0 auto;
语法:flex:none | [flex-grow] | [flex-shrink] | [flex-basis]
[ flex-grow ]:定义弹性盒子元素的扩展比率
[ flex-shrink ]:定义弹性盒子元素的收缩比率
[ flex-basis ]:定义弹性盒子元素的默认基准
flex属性定义子元素分配剩余空间,用 flex 表示占了多少份数。
flex 属性可以指定1个,2个或3个值。
单值语法:
一个无单位数(<number>)
一个有效的宽度值(width)
关键字none,auto,或是initial
flex:none |
flex:0 1 auto 完全不伸缩,僵化 |
flex:initial |
flex:0 1 auto 不能生长,但是缺乏空间时可以缩小 |
flex:auto |
flex:1 1 auto 依照可用空间平均伸缩 |
flex:<position-number> |
flex:<position-number> 1 0 能屈能伸,属性值判定生长比例 |
双值语法:
第一个值必须是一个无单位数,定义子元素的拉伸。第二个值必须是以下之一:
一个无单位数(<number>),
一个有效的宽度值(width)
三值语法:
第一个值必须是一个无单位的number,定义子元素的拉伸程度 flex-grow
第二个值必须是一个无单位的number,定义子元素的收缩规则 flex-shrink
第三个值必须为一个有效的宽度值,元素在主轴上的初始大小 flex-basis
HTML代码:
<section> <div></div> <div></div> <div></div> </section>
实例:
1、三个弹性子元素平分页面空间。
flex 属性设置为单个数值的 计算规则:如果子元素没有设置宽度 所有设置了 flex的子元素 数值之和为总共的份数
在这个例子中,共有三个元素都设置了flex:1 ;所以三个元素分别占据 弹性容器的 1/3
section{ width:60%; height: 100px; margin:100px auto; display:flex; border:tomato 2px solid; } section div:nth-child(1){ flex:1; background-color: burlywood; } section div:nth-child(2){ flex:1; background-color:goldenrod; } section div:nth-child(3){ flex:1; background-color: gold; }
3、圣杯布局
section{ width:60%; height: 100px; margin:100px auto; display:flex; border:tomato 2px solid; } section div:nth-child(1){ width: 100px; height:100px; background-color: burlywood; } section div:nth-child(2){ flex:1; background-color:goldenrod; } section div:nth-child(3){ width: 100px; height:100px; background-color: gold; }
3、flex:auto;
auto等价与 1 1 auto,flex-grow为1,flex-shrink为 1,flex-basis 为auto;
剩余的空间被自动平均分配
section{ width:600px; display:flex; border:tomato 2px solid; } section div{ width: 70px; height:70px; flex: auto; border:goldenrod 1px solid; background-color: gold; }
4、flex:none;
none等价于0 0 auto,flex-grow为0,flex-shrink为 0,flex-basis 为auto;
子元素宽度高度保持原有情况不拉伸,不缩放。
section{ width:600px; display:flex; border:tomato 2px solid; } section div{ width: 70px; height:70px; flex: none; background-color: gold; }
三、align-self 控制子 项自己在侧轴上的排列方式
align-self 属性允许单个项目有和其他项目不一样的对齐方式,可以覆盖 align-items 属性
默认值为 auto,表示继承父元素的align-items,如果没有父元素,则等同于 stretch。
属性值 | 说明 |
auto | 如果align-self值为 auto,则计算值为元素父元素的 align-items,如果其没有父元素,则计算值为 stretch |
flex-start | 弹性盒子元素的侧轴(纵轴)起始位置紧靠住该行的侧轴起始位置 |
flex-end | 弹性盒子元素的侧轴(纵轴)起始位置的边界紧靠住该行的侧轴结束边界 |
center | 子元素在该行侧轴上居中放置。(如果该行的尺寸小于弹性盒子元素的尺寸,则会向两个方向溢出相同的长度) |
stretch | 如果指定侧轴的大小的属性值为 ‘auto’,则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同事会遵照 ‘min’/max-width/height' 属性的限制 |
baseline | 如弹性盒子元素的行内轴与侧轴为同一条,该值与 ‘flex-start’等效。其他情况下,该值将参与基线对齐 |
align-self:用于设置弹性元素自身在侧轴方向上的对齐方式
语法:align-self:auto | flex-start | flex-end | center | baseline | stretch
实例:
div:nth-child(1){align-self: auto;} div:nth-child(2){align-self:flex-start;} div:nth-child(3){align-self:flex-end;} div:nth-child(4){align-self:stretch} div:nth-child(5){align-self:baseline} div:nth-child(6){align-self: center;}
四、order 子元素出现的顺序
设置或检索弹性盒模型子元素出现的顺序
语法:order:<integer>
属性值:<integer>:整数,使用整数来定义排列的顺序,数值最小的排在最前面。可以为负值
先后顺序为:……-2 、-1 、0 、1 、2 、3……。元素的默认值是 order:0
实例:
正常情况下的子元素排列顺序:
div:nth-child(1){ order:1; } div:nth-child(4),
div:nth-child(5){ order:2; } div:nth-child(3){ order:-1; }
弹性布局的小妙用:
一、自动margin
在弹性容器内的子元素会被当做是弹性项目
为弹性子元素设置 margin:auto可以实现元素在弹性容器中的水平垂直居中
HTML
<div class="box"> <div class="child"></div> </div>
CSS
.box{ display:flex; } .child{ margin:auto; }