布局的传统解决方案,基于盒状模型,依赖display+position+float属性。他对于特殊布局非常不方便,比如垂直居中。
而flex布局可以简便、完整、响应式的实现各种布局。设置为flex布局后,子元素的float属性、position属性和display属性都会失效。
flex弹性盒子模型,是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。
任何一个容器都可以指定为flex布局。
基本概念:
1、弹性盒子由弹性容器(flex container)和弹性子元素(flex item)组成。
注意:弹性容器外以及弹性子元素内是正常渲染的。弹性盒子只是定义了弹性子元素如何在弹性容器内布局。
2、Flex是没有方向之分的,在flex容器中默认存在两根轴,水平的轴为主轴main axis,垂直的轴为 侧轴cross axis。(如果改变flex-direction,主轴和侧轴也将会改变)。
容器(父元素)的属性:
容器共有六个属性
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
flex-direction属性
flex-direction属性决定主轴的方向,它可能有四个值。
- row:默认值,主轴为水平方向,起点在左端。
- row-reverse:主轴在水平方向,起点在右端。
- column:主轴为垂直方向,起点在上端。
- column-reverse:主轴在垂直方向,起点在下端。
flex-wrap属性
flex-wrap属性决定项目在一行排不下的情况下是否换行,它可能有三种值。
- nowrap:默认值,不换行。
- wrap:换行,第一行在主轴开始方向,依次往主轴结束方向布局。
- wrap-reverse:换行,第一行在主轴结束方向,依次往主轴开始方向布局。
flex-flow属性
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值是row nowrap。
justify-content属性
justify-content属性定义了项目在主轴上的对齐方式,它可能有五个值。
- flex-start:默认值,主轴开始方向对齐。
- flex-end:主轴结束方向对齐。
- center:主轴居中对齐。
- space-between:两端对齐,项目之间间隔都相等。
- space-around:每个项目两侧的间隔相等。
align-items属性
align-items属性定义了每行项目在侧轴方向的对齐方式,它可能有五个值。
- flex-start:侧轴开始方向对齐。
- flex-end:侧轴结束方向对齐。
- center:侧轴居中方向对齐。
- baseline:项目第一行文字的基线对齐。
- stretch:默认值,如果项目未设置高度或高度设为auto,将占据整个容器。
假设侧轴从上到下,五种值对应情况如下图所示:
align-content属性
align-content属性定义了容器在侧轴方向上有额外空间时,如何每排布一行,当容器只有一行时,它不起作用,它可能有六个值。
- flex-start:侧轴开始方向对齐。
- flex-end:侧轴结束方向对齐。
- center:侧轴中心对齐。
- space-between:与侧轴两端对齐,每行轴线间隔平均。
- space-around:每根轴线两侧间隔相等。
- stretch:默认值,占满整个侧轴。
假设侧轴从上到下,六种值对应的情况如下图所示:
子元素的属性
子元素共有六个属性
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
order属性
order属性定义了项目的排列顺序,数值越小排列越靠前,默认为0。
flex-grow属性
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间也不放大。
如果所有项目的flex-grow属性都为1,则他们将等分剩余空间。
flex-shrink属性
flex-shrink属性定义了项目的缩小比例,默认值为1,即如果空间不足该项目将缩小。
负值对该属性无效,即该属性的可能值为0或正整数。
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小,如下图所示:
flex-basis属性
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据整个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
flex属性
flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。后两个属性可选。
该属性有两个快捷值:auto (1 1 auto)
(既可以放大占满空间,也可缩小) 和 none (0 0 auto)
(不可放大,也不可缩小)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
align-self属性
align-self属性允许单个项目与其他项目不一样的侧轴对齐方式,可覆盖align-items属性,默认值为aoto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
其值出auto外,其他与align-items完全一致。
之前我们是这样实现一个div盒子水平垂直居中的。在知道对象高宽的情况下,对居中元素绝对百分比定位,然后通过margin偏移的方式来实现。
假如使用了flex后,实现起来就简单了,而且不需要自己去算,也不需要绝对定位,只需要通过对伸缩容器定义两个属性,justify-content定义伸缩项目沿着主轴线的对齐方式为center, align-items定义伸缩项目在侧轴(垂直于主轴)的对齐方式为center,具体如下:
关于伸缩项目的相关属性,主要是3个,order,flex(flex-grow,flex-shrink,flex-basis的组合),align-self;用来比较多的是前两个。
order
有一种用法比较多,想设置一组中有两个元素一个排第一,另外一个排最后,主需要将第一个的order:-1;另一个为order:0;这样就好了。
譬如我们想控制一个container中有4个box,想box4为一个显示,box1为最后一个显示。只需要 这样
常见问题
1、兼容方案:父级flex布局
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- H5不用考虑 */ display: -mz-flexbox; /* TWEENER IE 10 */ display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
2、子元素设置flex:1;代表什么意思?
flex是flex-grow、flex-shrink、flex-basis的缩写。 默认为flex:0 1 auto;
(1)flex=none;等价于flex:0 0 auto;
(2)flex=auto;等价于flex:1 1 auto;
(3)当flex取值为一个非负数字时,该数字为flex-grow的值,flex-shrink取1,flex-basis取0%
如flex:1;等价于flex:1 1 0%;
(4)当flex取值为一个长度或百分比,则视为flex-basis的值,flex-grow取1,flex-shrink取1
如flex:0%;等价于flex:1 1 0%;
flex:24px;等价于flex:1 1 24px;
(5)当flex取值为两个非负数字时,则分别视为flex-grow和flex-shrink的值,flex-basis取0%
如flex:2 3;等价于flex:2 3 auto;
3、对于flex-grow放大比例的问题:
(1)当子元素宽度写在width里 (是按照父元素的宽度进行等比划分)
.container{ 1000px; display: flex; border: solid 2px #000000; } .demo1{ 200px; flex: 1; background: red; } .demo2{ 200px; flex: 1; background: yellow; } .demo3{ 200px; flex: 2; background:blue; }
最终效果
(2)把子元素的宽度写在flex-basis里 (是按照剩余空间进行比例划分)
.container{ 1000px; display: flex; border: solid 2px #000000; } .demo1{ flex: 1 1 200px; background: red; } .demo2{ flex: 1 1 200px; background: yellow; } .demo3{ flex: 2 1 200px; background:blue; }
最终效果:
3、父元素的align-items与align-content的区别
align-items只适用于子项目为单行的情况,对多行子元素有如下情况
(1)当父元素不设高度时,每一行的高度为该行子项中高度最大的那个值。各行的子项在各自行上居中。
.con{ 700px; display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; } .sub{ 100px; height: 100px; background: red; } .sub1{ 100px; height: 50px; background: blue; } <div class='con'> <div class='sub'></div> <div class='sub1'></div> <div class='sub'></div> <div class='sub'></div> <div class='sub1'></div> <div class='sub'></div> <div class='sub'></div> <div class='sub1'></div> </div>
(2)当父元素设置高度时,flex容器会将多余的空间平分给每一行,然后每一行的子元素在各自行对齐。
align-content只适用与多行的flex容器(即有多行子元素),当只有一行子元素时不起作用。
.con{ 700px; height: 400px; background: yellow; border: solid 1px #000000; display: flex; flex-direction: row; align-content: center; } .sub{ 100px; height: 100px; background: red; border: solid 1px #000000; }
<div class='con'>
<div class='sub'></div>
<div class='sub'></div>
</div>
效果(单行元素不起作用)
如果添加多个子元素,并且flex-wrap:wrap;效果如下:(多行元素)
4、flex-shrink的计算方式
//求下列布局在页面上的宽度比 .flex{ display: flex; 200px; height: 100px; } .left{ flex: 3 2 50px; } .right{ flex: 2 1 200px; }
解析:因为子元素的宽度和为50px+200px=250px超过了父元素的宽度,所以要进行缩放。
浏览器将超出的空间,按照收缩因子相加之后计算比率来进行空间收缩。
超出的空间:250px-200px=50px;这超出的50px需要被这两个子元素消化。
按照收缩因子,加权综合可得:50*2+200*1=300px;
于是我们可以计算每个子元素将被移除的溢出量是多少:
收缩因子为2的,被移除溢出量:(50*2)/300*50px=50/3;
收缩因子为1的,被移除溢出量:(100*1)/300*200=100/3;
最后实际宽度比为:(50-50/3):(200-100/3)=1:5