html&css
弹性布局
简介
- 传统布局基于盒子模型,通过 display float position 属性进行布局,但是有些效果在盒模型下不好实现,比如垂直方向居中。
- 2009年 W3C 提出Flex布局,主流浏览器均可支持,其中IE浏览器在IE10之后开始支持
基础语法
概念
Flex容器
- 采用Flex布局的元素,称为Flex容器(flex container)。它的所有子元素自动成为容器成员,称为Flex项目(flex item)
- 给元素添加 display: flex 属性使元素成为Flex容器,即开启了弹性布局,行内元素也可用 display: inline-flex; 成为Flex容器
- 开启弹性布局后Flex容器的子元素的 float clear vertical-align 属性将失效
主轴和副轴
- 在Flex容器内使用主轴和副轴概念;默认x轴为主轴,y轴为副轴;可由Flex容器的 flex-direction 属性修改
- 主轴副轴中有起始位置的概念,默认的起始位置为x轴的左侧y轴的上侧
- 在使用弹性布局时,需要通过主轴和副轴确定编辑的方向,Flex容器内的元素默认会处于类似 float 的状态,例html结构如下:12345<div class="container"><div class="pink"></div><div class="green"></div><div class="blue"></div></div>
当主轴为x轴时:
当主轴为y轴时:
即主轴方向决定了容器内元素的排列方向
容器属性
flex-direction
flex-wrap
flex-flow
justify-content
align-items
align-content
1. flex-direction
设置主轴方向
row(默认值):主轴为x轴,起始位置为左
row-reverse:主轴为x轴,起始位置为右
column:主轴为y轴,起始位置为上
column-reverse:主轴为y轴,起始位置为下
2. flex-wrap
设置可换行属性,默认下容器内子元素会按照主轴方向排一行,不会换行,当总长度超过容器时子元素会被压缩,通过 flex-wrap 属性可设置换行模式
nowrap(默认值):不换行,width设置为22%的6个子元素被压缩在一行
wrap:换行,第一行从最上侧开始
wrap-reverse:换行,第一行从最底部开始
3. flex-flow
flex-direction 和 flex-wrap 的联写模式
4. justify-content
设置主轴方向的对其方式
flex-start(默认值):左对齐
flex-end:右对齐
center: 居中
space-between:两端对齐,项目之间的间隔都相等。
space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
5. align-items
设置副轴方向对其方式
flex-start:副轴的起点对齐
flex-end:副轴的终点对齐
center:副轴的中点对齐
baseline: 项目的第一行文字的基线对齐
stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度
这里只演示baseline效果,其它类似于justify-content的效果
6. align-content
在开启换行模式后有换行时设置多行在副轴方向的对齐方式,如果主轴只有一行则该属性无效
flex-start:与交叉轴的起点对齐
flex-end:与交叉轴的终点对齐
center:与交叉轴的中点对齐
space-between:与交叉轴两端对齐,轴线之间的间隔平均分布
space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍
stretch(默认值):轴线占满整个交叉轴
子元素属性
order
flex-grow
flex-shrink
flex-basis
flex
align-self
1. order (常用)
定义子元素排列顺序,值为无单位整数,默认值为0,值越小越靠近起始位置
2. flex-grow
- 定义子元素放大比例,只有在容器主轴方向大小大于子元素总大小时才有效果,即容器有空余,值为无单位非负数字,可设置浮点数,默认为0
- 当值为0时代表子元素不放大,如果容器有剩余空间则空出
- 如果有子元素 flex-grow 值不为0,则子元素会按照 flex-grow 值的比例放大并填充容器的剩余空间

具体计算方式:假设 A, B, C, D, E 的宽度分别是 100, 120, 130, 100, 100,父级的宽度是660,父级宽减去子级的全部宽度,这样剩余空间就是110。例子中B, C定义了flex-grow,分别是1,2,那剩余空间分成3份,B1份,C2份,比例就是1:2,分配计算出来的值就是B :36.666666666666664, C:73.33333333333333。这个时候剩余空间就被计算出来了,相加后的结果就是B:156.66666666666666,C:203.33333333333331。
B的计算公式:120 + (110 / 3) * 1
C的计算公式: 130 + (110 / 3) * 2
3. flex-shrink
- 定义子元素缩小比例,只有在容器主轴方向大小小于子元素总大小且不换行时才有效果,即容器空间不足,值为无单位非负数字,可设置浮点数,默认为1
- 为0表示子元素不缩小,如果容器大小小于子元素总大小,而所有子元素均不缩小,则子元素会超出容器范围
- 如果有子元素 flex-shrink 值不为0,则子元素会按照 flex-shrink 值的比例缩小在容器中

具体计算方式:假设 A, B, C 的宽度分别是155, 200, 50。父级宽度是300,计算超出的空间就是 -105,这样超出的 105px 就要被 A, B, C 消化掉,比例是2:1:1。
首先把每个项目的wdith值乘以 flex-shrink 值求积
A:(155 * 2) = 310
B:(200 * 1) = 200
C:(50 * 1) = 50。
然后再求和所有项目的乘积
(310 + 200 + 50) = 560
得到求占比之后还要乘以要腾出的空间
A:(310 / 560) * 105 = 58.125
B:(200 / 560) * 105 = 37.5
C:(50 / 560) * 105 = 9.375
得到每一项要腾出的空间
A:(155 - 58.125) = 96.875
B:(200 - 37.5) = 162.5
C:(50 - 9.375) = 40.625
这就是 A, B, C 按比例缩小后的大小
4. flex-basis
- 本人对于 flex-basis 的意义并没有完全理解,个人感觉有点像是设置了一个 max-width (主轴x轴时),很多人推荐在弹性布局中多使用 flex-basis 而不是直接设置 width height 属性,这个属性在下面的圣杯布局实例中有一次使用
- 它的默认值为 auto,表示项目的本来大小
5. flex (常用)
- flex-grow flex-shrink flex-basis 的联写,默认值为0 1 auto。后两个属性可选
- 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)
- 通常直接用 flex 设置子元素比例大小,例如使用 flex: 1 直接设置大小比例,而不再单独写 flex-grow: 1
6. align-self (常用)
- align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch(默认值)
- 除多出默认值 auto 外,属性值同 align-items

应用实例
圣杯布局
- 圣杯布局是指在页面主体部分分为 left content right 3部分,left和right固定大小,content部分会自适应屏幕大小,后来国内的淘宝团队对其进行了改良,改良后效果基本相同,一般叫做双飞翼布局,使用搜索引擎搜索有很多相关介绍
- 本身圣杯布局是使用 float margin padding 和定位等盒模型方法实现的,关键点是使用负值的 margin 使left和right可以与设置为100%宽度的content浮动在同一行中,这里使用弹性布局则可以非常方便清晰的实现有自适应效果的圣杯布局
html结构:
css样式:
效果图:
这里做了屏幕大小判断来适应移动端,在设置left和right宽度时使用的是 flex-basis,而不是 width,主要是因为在判断屏幕宽度小于768px时需要层叠掉left和right原本的固定宽度,让left和right可以自动填充整个屏宽,使用 flex-basis 可以在移动端样式中直接设置 flex: 1 使 flex-basis 变为 auto,如果使用 width,在需要去掉固定宽度时则比较麻烦
使用弹性布局不仅在宽度上达到自适应,在高度上也可以不受内容限制,直接填充满整个屏高
悬窗图片展示板
- 利用弹性布局可以用很少的代码制作一个图片悬窗的图片展示板,弹性布局在处理宽高位置等方面非常方便,实用的demo有很多,这里就只展示一个悬窗案例
html:
css:
效果图:
结尾
本文参考了阮一峰的博客,并且很无耻的直接使用了其中的一些说明图片 ^-^ ;这里先谢阮大神,但是个人感觉阮一峰这篇博客对于一些属性的说明不太详细。
在 flex-grow 和 flex-shrink 的具体计算上直接使用了xiecg的文章中的例子,因为这个例子写的实在是太棒了。









