一、概述
布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如垂直居中就不容易实现。
2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。
任何一个容器都可以设置为Flex布局
1 .box { 2 display: flex; 3 }
行内元素也可以使用Flex布局
1 .box { 2 display: inline-flex; 3 }
在IE10中需要使用-ms-前缀;UC浏览器需要使用-webkit-前缀。
1 .box { 2 display: -ms-flex; 3 display: -webkit-flex; 4 display: flex; 5 }
IE11 已经支持display: flex,但是在使用的时候会有一些bug。
二、基本概念
1、Flex容器与项目
当一个元素使用了Flex布局时,我们就称该元素为Flex容器(Flex container),简称为“容器”;同时该元素中的所有子元素都会成为容器成员,我们称它们为Flex项目(Flex item),简称为“项目”。
每个容器都有两条轴线:主轴和交叉轴,交叉轴垂直于主轴,默认情况下,水平方向上的是主轴,垂直方向上的是交叉轴,主轴的起始位置叫做main start,终止位置叫做main end;交叉轴的起始位置叫做cross start,终止位置叫做cross end。
Flex项目默认沿着主轴方向排列,一个项目在主轴上占用的空间为main size,在交叉轴占用的空间为cross size。
2、Flex容器上的属性
1)flex-direction
- 作用:用于设置主轴方向,即flex项目的排列方向
- 取值:
- row
- row-reverse
- column
- column-reverse
- 详解:
- row:默认值,设置主轴沿水平方向,起始位置在左侧,终止位置在右侧
1 <div class="main"> 2 <div class="box">1</div> 3 <div class="box">2</div> 4 <div class="box">3</div> 5 <div class="box">4</div> 6 </div>
1 .main { 2 width: 600px; 3 height: 200px; 4 border: 1px solid red; 5 display: flex; 6 justify-content: space-around; 7 align-items: center; 8 margin: 50px auto; 9 } 10 11 .box { 12 width: 100px; 13 height: 40px; 14 background-color: pink; 15 text-align: center; 16 }
-
row-reverse:设置主轴沿水平方向,起始位置在右侧,终止位置在左侧
1 .main { 2 ... 3 flex-direction: row-reverse; 4 ... 5 }
-
column:主轴方向与交叉轴方向交换,即主轴沿垂直方向,且起始位置在顶部,终止位置在底部
1 .main { 2 ... 3 flex-direction: column; 4 ... 5 }
-
column-reverse:主轴方向与交叉轴方向交换,即主轴沿垂直方向,且起始位置在底部,终止位置在顶部
1 .main { 2 ... 3 flex-direction: column-reverse; 4 ... 5 }
- row:默认值,设置主轴沿水平方向,起始位置在左侧,终止位置在右侧
2)flex-wrap
- 作用:用于设置容器中的项目是否换行展示,以及换行的方式。
- 取值:
- nowrap
- wrap
- wrap-reverse
- 详解
- nowrap:默认值,不换行。当容器中所有项目的总宽度超过该容器的最大宽度时,会将项目进行收缩,避免溢出容器,如果项目不能进行收缩或者收缩程度不够时,会出现溢出容器的情况。
1 .main { 2 width: 600px; 3 height: 200px; 4 margin: 40px auto; 5 border: 1px solid red; 6 display: flex; 7 align-items: center; 8 flex-wrap: wrap; 9 } 10 .box { 11 width: 100px; 12 height: 40px; 13 box-sizing: border-box; 14 text-align: center; 15 background-color: pink; 16 box-sizing: border-box; 17 border: 1px solid black; 18 }
如上图,每个项目的宽度为100px,当所有项目的总宽度(8*100px)超过容器的最大宽度(600px)时,会自动收缩每个项目为75px(600 / 8),达到不溢出容器的效果。
如果我们设置每个项目的最小宽度为100px,那么此时会出现什么情况呢?
1 .box { 2 min-width: 100px; 3 ... 4 }
此时由于规定了每个项目的宽度为100px,此时所有项目收缩到100px时,就无法再进行收缩,因此会出现溢出的情况。
- wrap:换行,即当容器中所有项目的总宽度超过该容器的最大宽度时,不会收缩项目,而是直接进行换行,并且按照先出现的在上面的方式进行换行。
1 .main { 2 ... 3 flex-wrap: wrap; 4 }
-
wrap-reverse:换行,且按照先出现的在下方的方式进行换行。
1 .main { 2 ... 3 flex-wrap: wrap-reverse; 4 }
- nowrap:默认值,不换行。当容器中所有项目的总宽度超过该容器的最大宽度时,会将项目进行收缩,避免溢出容器,如果项目不能进行收缩或者收缩程度不够时,会出现溢出容器的情况。
3)flex-flow:
- 作用:该属性是flex-direction和flex-wrap两个属性的简写,默认为 row nowrap;
1 .main{ 2 flex-flow: <flex-direction> | <flex-wrap> 3 }
4)justify-content
- 作用:设置容器中的项目在主轴上的对齐方式
- 取值:
- flex-start
- flex-end
- center
- space-between
- space-around
- 详解
- flex-start:默认值,沿主轴起始位置对齐
-
- flex-end:沿主轴终止位置对齐
-
- center:沿主轴居中
-
- space-between:两端对齐,项目之间的间隔相等
-
- space-around:每个项目两侧之间的距离相等,因此两个项目之间的距离是项目与容器两端距离的两倍。
5)align-items
- 作用:设置容器中的项目在交叉轴上的对齐方式
- 取值:
- stretch
- flex-start
- flex-end
- center
- baseline
- 详解:
- stretch:默认值,沿交叉轴起始位置对齐,如果项目没有高度或者设置高度为auto,则将占满整个容器的高度
- flex-start:沿交叉轴起始位置对齐
-
- flex-end:沿交叉轴终止位置对齐
-
- center:沿交叉轴居中
-
- baseline:沿项目中的第一行文字的基线对齐
6)align-content
- 作用:设置容器中的项目在交叉轴的排列方式,如果容器只有一条轴线,该属性不生效,因此需要与flex-wrap组合使用。
- 取值:
- strect
- flex-start
- flex-end
- center
- space-between
- space-around
- 详解:
- strect:默认值,轴线占满整个交叉轴;我觉得比较有有画面感的解释:将容器沿交叉轴进行n等分(n为容器中主轴线的条数),每条主轴上的元素独占每等分空间,并按照align-items属性进行排列。
1 .main { 2 ... 3 display: flex; 4 align-content: stretch; 5 flex-wrap: wrap; 6 }
- strect:默认值,轴线占满整个交叉轴;我觉得比较有有画面感的解释:将容器沿交叉轴进行n等分(n为容器中主轴线的条数),每条主轴上的元素独占每等分空间,并按照align-items属性进行排列。
-
- flex-start:容器中的项目沿交叉轴的起始位置对齐
1 .main { 2 ... 3 display: flex; 4 align-content: flex-start; 5 flex-wrap: wrap; 6 } 7
-
flex-end:容器中的项目沿交叉轴的终止位置进行排序
1 .main { 2 ... 3 display: flex; 4 align-content: flex-end; 5 flex-wrap: wrap; 6 }
-
center:容器中的项目沿交叉轴的中间位置对对齐
1 .main { 2 ... 3 display: flex; 4 align-content: center; 5 flex-wrap: wrap; 6 }
-
space-around:容器中每条主轴的两侧间隔相等,因此相邻两条主轴之间的间隔比主轴与交叉轴两端的间隔大一倍。
1 .main { 2 ... 3 display: flex; 4 align-content: space-around; 5 flex-wrap: wrap; 6 }
-
space-between:容器中的项目与交叉轴两端对齐,主轴之间的间隔均等分布。
1 .main { 2 ... 3 display: flex; 4 align-content: space-between; 5 flex-wrap: wrap; 6 } 7
- flex-start:容器中的项目沿交叉轴的起始位置对齐
3、Flex项目上的属性
1)flex-basis
- 作用:设置项目在主轴上占用的空间,浏览器根据该属性的值来计算主轴是否还存在多余空间。
- 取值:
- auto
- px
- 详解:
- auto:默认值,此时,浏览器会检测这个元素是否具有确定的尺寸,如果元素有确定的尺寸,flex-basis的值采用该尺寸,如果没有给元素设定尺寸,
flex-basis
的值采用元素内容的尺寸。比如下面的例子,项目的width为100px,所以flex-basis也是100px。1 .box { 2 width: 100px; 3 ... 4 flex-basis: auto; 5 }
-
px:flex-basis也可以像设置width属性一样设置具体的px值,即使此时元素设置了确定的尺寸,也要采用flex-basis的值。
1 .box { 2 width: 100px; 3 ... 4 flex-basis: 120px; 5 }
- auto:默认值,此时,浏览器会检测这个元素是否具有确定的尺寸,如果元素有确定的尺寸,flex-basis的值采用该尺寸,如果没有给元素设定尺寸,
2)flex-grow
- 作用:根据flex-basis属性检测浏览器是否存在剩余空间,如果存在则将项目进行伸展以填充剩余空间
- 取值:数字
- 详解:
- flex-grow的默认值为0,表示不伸展。
1 .box { 2 ... 3 flex-basis: 120px; 4 flex-grow: 0; 5 }
-
如果给容器中所有项目的flex-grow都设置为1,则所有项目均分剩余空间。
1 .box { 2 ... 3 flex-basis: 120px; 4 flex-grow: 1; 5 }
-
如果给容器中的某个项目的flex-grow设置为2,其余项目都设置为1,则为2的项目占剩余空间的2/5,其他项目占1/5。
1 .box:first-child { 2 flex-grow: 2; 3 }
可以看出box1比其他box要大。
- flex-grow的默认值为0,表示不伸展。
3)flex-shrink
- 作用:当容器中的项目超出主轴空间时,收缩项目至主轴不溢出。
- 取值:数字
- 详解:
- 1:默认值,即当超出主轴空间时,该项目将收缩。
1 .main{ 2 ... 3 flex-wrap: nowrap 4 } 5 .box { 6 ... 7 flex-basis: 200px; 8 flex-shrink: 1; 9 }
-
0:表示不收缩
1 .box:first-child { 2 flex-shrink: 0; 3 }
如上图,第一个box没有收缩,其他box收缩了。
- 1:默认值,即当超出主轴空间时,该项目将收缩。
4)flex
- 作用:该属性是flex-grow、flex-shrink、flex-basis三个属性的缩写
- 取值:
- auto:表示1 1 auto
- none:表示0 0 auto
- flex-grow | flex-shrink |flex-basis
5)order
- 作用:用于指定项目的排列顺序,值越小越靠前,值越大就越靠后,默认为0。
- 详解:
- 默认为0,当把容器中的两个项目分别设置为-1和1,来看一下效果
1 .box:nth-child(2) { 2 order: -1; 3 } 4 5 .box:nth-child(3) { 6 order: 1; 7 }
- 默认为0,当把容器中的两个项目分别设置为-1和1,来看一下效果
6)align-self
- 作用:当容器中的某个项目与其他项目在交叉轴的对齐方式与其他项目不一样时,使用该属性可以实现。
- 取值:
- auto
- 其他取值与align-items一样
- 详解:
- auto:默认值,继承父元素的align-items的值
- 其他取值与align-items一样,举个例子说明一下
1 .main { 2 ... 3 display: flex; 4 align-items: flex-start; 5 } 6 7 .box:nth-child(2) { 8 align-self: flex-end; 9 } 10 11 .box:nth-child(3) { 12 align-self: center; 13 }
如上图,容器的align-items值为flex-start,所有项目本应该沿交叉轴起始位置对齐,但是容器中的第二个项目的align-self设置为flex-end,因此它沿终止位置对齐,第三个项目的align-self设置为center,因此它中间对齐。