本文主要参考 CSS 伸缩盒布局模组,主要介绍的是应用在元素身上的 flex
属性取值的问题,关于 flex
布局的一些知识可以参考 flex 布局,故本文不会涉及太多
需要注意的是,如果将元素的
display
属性设置为flex
,那么其就转换为了flex
容器,在设为flex
容器后,其子元素的float
、clear
和vertical-align
属性都将失效
下面我们就先来简单了解 flex
布局常用的属性和一些取值介绍,其实它主要分为两部分,一个是应用在容器上的属性,另一个是应用在子容器上的属性
容器的属性
有下面六个属性是应用在容器上面的
flex-direction
,属性决定主轴的方向(即项目的排列方向)row
(默认值),主轴为水平方向,起点在左端row-reverse
,主轴为水平方向,起点在右端column
,主轴为垂直方向,起点在上沿column-reverse
,主轴为垂直方向,起点在下沿
flex-wrap
,默认情况下,项目都排在一条线(轴线)上,如果一条轴线排不下,如何换行nowrap
(默认),不换行wrap
,换行,第一行在上方wrap-reverse
,换行,第一行在下方
flex-flow
,为flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
justify-content
,定义了项目在主轴上的对齐方式(左右)flex-start
(默认值),左对齐flex-end
,右对齐center
, 居中space-between
,两端对齐,项目之间的间隔都相等space-around
,每个项目两侧的间隔相等,所以,项目之间的间隔比项目与边框的间隔大一倍
align-items
,定义项目在交叉轴上如何对齐(上下)flex-start
,交叉轴的起点对齐flex-end
,交叉轴的终点对齐center
,交叉轴的中点对齐baseline
,项目的第一行文字的基线对齐stretch
(默认值),如果项目未设置高度或设为auto
,将占满整个容器的高度
align-content
,定义了多根轴线的对齐方式如果项目只有一根轴线,无效(意思就是内容分为多行,类似line-height
)flex-start
,与交叉轴的起点对齐flex-end
,与交叉轴的终点对齐center
,与交叉轴的中点对齐space-between
,与交叉轴两端对齐,轴线之间的间隔平均分布space-around
,每根轴线两侧的间隔都相等,所以,轴线之间的间隔比轴线与边框的间隔大一倍stretch
(默认值),轴线占满整个交叉轴
元素的属性
有下面六个属性是应用在元素身上的
order
,定义项目的排列顺序,数值越小,排列越靠前,默认为0
flex-grow
,定义项目的放大比例,默认为0
,即如果存在剩余空间,也不放大- 如果所有项目的
flex-grow
属性都为1
,则它们将等分剩余空间(如果有的话) - 如果一个项目的
flex-grow
属性为2
,其他项目都为1
,则前者占据的剩余空间将比其他项多一倍(类似合并单元格)
- 如果所有项目的
flex-shrink
,定义了项目的缩小比例,默认为1
,即如果空间不足,该项目将缩小- 如果所有项目的
flex-shrink
属性都为1
,当空间不足时,都将等比例缩小 - 如果一个项目的
flex-shrink
属性为0
,其他项目都为1
,则空间不足时,前者不缩小
- 如果所有项目的
flex-basis
,定义了在分配多余空间之前,项目占据的主轴空间- 浏览器根据这个属性,计算主轴是否有多余空间,它的默认值为
auto
,即项目的本来大小 - 它可以设为跟
width
或height
属性一样的值,则项目将占据固定空间
- 浏览器根据这个属性,计算主轴是否有多余空间,它的默认值为
flex
,是flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
,后两个属性可选align-self
,允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性(父级容器指定的排列方式)- 默认值为
auto
,表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch
- 除了
auto
,其他都与align-items
属性完全一致
- 默认值为
flex
之前也提到过了,本章主要介绍的就是关于子容器属性上的 flex
取值问题,所以我们下面就来看看这个属性的一些特殊之处,我们都知道,其实子属性身上的 flex
属性是 flex-grow
、flex-shrink
、flex-basis
的缩写,flex
的默认值是以上三个属性值的组合,假设以上三个属性同样取默认值,则 flex
的默认值是 0 1 auto
,如下,是等同的
1 | .item {flex: 222 233 244px;} |
当 flex
取值为 none
,则计算值为 0 0 auto
,如下是等同的
1 | .item {flex: none;} |
当 flex
取值为 auto
,则计算值为 1 1 auto
,如下是等同的
1 | .item {flex: auto;} |
当 flex
取值为一个非负数字,则该数字为 flex-grow
值,flex-shrink
取 1
,flex-basis
取 0%
,如下是等同的
1 | .item {flex: 1;} |
当 flex
取值为一个长度或百分比,则视为 flex-basis
值,flex-grow
取 1
,flex-shrink
取 1
,有如下等同情况,注意 0%
是一个百分比而不是一个非负数字
1 | .item-1 {flex: 0%;} |
当 flex
取值为两个非负数字,则分别视为 flex-grow
和 flex-shrink
的值,flex-basis
取 0%
,如下是等同的
1 | .item {flex: 2 3;} |
当 flex
取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow
和 flex-basis
的值,flex-shrink
取 1
,如下是等同的
1 | .item {flex: 2333 3222px;} |
flex-basis
规定的是子元素的基准值,所以是否溢出的计算与此属性息息相关,flex-basis
规定的范围取决于 box-sizing
,这里主要讨论以下 flex-basis
的取值情况
auto
首先检索该子元素的主尺寸,如果主尺寸不为auto
,则使用值采取主尺寸之值,如果也是auto
,则使用值为content
content
指根据该子元素的内容自动布局,有的用户代理没有实现取content
值,等效的替代方案是flex-basis
和主尺寸都取auto
- 百分比 根据其包含块(即伸缩父容器)的主尺寸计算,如果包含块的主尺寸未定义(即父容器的主尺寸取决于子元素),则计算结果和设为
auto
一样
实例
下面我们来看一个实例加深一下印象,页面布局如下
1 | <div class="parent"> |
应用的 CSS
如下
1 | .parent { |
最终效果如下
主轴上父容器总尺寸为 600px
,那么子元素的总基准值是 0% + auto + 200px = 300px
,其中
0%
即0
宽度auto
对应取主尺寸即100px
所以剩余空间为 600px - 300px = 300px
,伸缩放大系数之和为 2 + 2 + 1 = 5
,那么剩余空间分配如下
item-1
和item-2
各分配2/5
,各得120px
item-3
分配1/5
,得60px
所以各项目最终宽度为
item-1 = 0% + 120px = 120px
item-2 = auto + 120px = 220px
item-3 = 200px + 60px = 260px
当 item-1
基准值取 0%
的时候,是把该项目视为零尺寸的,故即便声明其尺寸为 9999px
,也并没有什么用,形同虚设,而 item-2
基准值取 auto
的时候,根据规则基准值使用值是主尺寸值即 100px
,故这 100px
是会用来计算基准值,而不会纳入剩余空间