这是一种全新的布局,在移动端非常实用,IE对此布局的相关的兼容不是很好,Firefox、Chrome、Safrai等需要加浏览器前缀。
先说说这种布局的特点:
1)移动端由于屏幕宽度都不一样,在布局的时候为了适配,如果用百分比,就得精确计算,而且如果有1px边框,计算会更加复杂难控制
2)如果有多列,要让所有列的高度一样,以前的话需要用各种计算或用子元素撑高等
3)上下居中,如果是在以前,那么用line-height或top绝对定位等计算
4)表单布局的时候,经常是左边和右边在一行上,以往是设置float或position与margin-left组合布局
5)网页有时候要有个底部,放些联系方式友情链接等,这个底部应该永远在下面,即使中间没内容,也不要移上来,以往的话是给中间赋个高等
而现在,用Flexible Box的几个属性就能完成上面的高难度动作。
1)几个基础概念
1. flex container(弹性容器),主要设置display为 flex 或 -webkit-flex ,那么这个容器中的子元素就是弹性的。
2. flex item(弹性子元素),尺寸可通过普通的width或height,或者使用高级的 flex 属性,自定义分配空间设置尺寸。
3. main axis(主轴或横轴)和cross axis(侧轴或纵轴),其中属性 flex-direction 、 justify-content 、 align-items 、 align-self 控制着轴的方向或对齐方式。
4. flex-wrap 属性可以控制弹性子元素的换行。
5. 有个 order 属性,用整数值来定义排列顺序,数值小的排在前面。
2)新旧属性对比
旧语法 | 新语法 |
旧版部分属性兼容性:
新版部分属性兼容性:
3)新旧属性对应
旧属性 | 新属性 | 定义或对比 |
box-orient box-direction | flex-direction | box-orient:horizontal + box-direction:normal = flex-direction:row box-orient:horizontal + box-direction:reverse = flex-direction:row-reverse box-orient:vertical + box-direction:normal = flex-direction:column box-orient:horizontal + box-direction:reverse = flex-direction:column-reverse |
box-flex | flex | flex有3个子属性,而box-flex只能设置一个数字 |
box-align | align-items align-content | 下面会分析align-items和align-content的区别 |
box-pack | justify-content | 效果相同 |
box-ordinal-group | order | 效果相同 |
box-lines (实验属性) | flex-wrap | 效果相同(Android的UC和微信浏览器没有换行效果) |
box-flex-group | 设置或检索伸缩盒对象的子元素的所属组 | |
flex-grow | flex子属性,设置或检索弹性盒的扩展比率 | |
flex-shrink | flex子属性,设置或检索弹性盒的收缩比率 | |
flex-basis | flex子属性,设置或检索弹性盒伸缩基准值 | |
flex-flow | flex-direction与flex-wrap的复合属性,设置或检索弹性盒模型对象的子元素排列方式 | |
align-self | 定义flex子项单独在侧轴(纵轴)方向上的对齐方式 |
4)align-content与align-items的区别
先看下面的对比图片,左边是align-content,右边是align-items( 在线代码请点击这里 ,用Chrome打开)
align-content 只有在多行的时候才会出现效果,如果只有一行就不会有效果,可以修改在线的代码看效果。此属性与在主轴上对齐方式的 justify-content 属性类似(Android上的UC和微信浏览器不显示flex-wrap效果)
align-items 在多行的时候,两列不是被当成了一个整体,但在一行的时候,效果很好。 align-self 修改的是父级 align-items 的效果。
5)子元素空间计算方式
新语法flex,里面包括 flex-grow 扩展比率、 flex-shrink 收缩比率和 flex-basis 起始数值。分两种情况:
1. 容器的宽度 > 子元素宽度总和, 查看在线源码 。
容器的宽度设置为500px, flex-basis 子元素起始宽度分别50px、80px、100px。
.flex li:nth-child(1) { flex: 1 1 50px; background:red; } .flex li:nth-child(2) { flex: 2 2 80px; background:blue; } .flex li:nth-child(3) { flex: 3 3 100px; background:black; }
先算出剩余空间为270px,用 flex-grow 来计算。
最终宽度 = flex-grow / flex-grow总和 * 剩余空间 + flex-basis
子元素1 = (1 / (1+2+3)) * 270 + 50= 95
子元素2 = (2 / (1+2+3)) * 270 + 80= 170
子元素3 = (3 / (1+2+3)) * 270 + 100= 235
2. 容器的宽度 < 子元素宽度总和, 查看在线源码 。
容器的宽度设置为110px, flex-basis 子元素的属性和上面相同。
先算出溢出值120px,再根据收缩比率,计算出收缩总和 1*50 + 2*80 + 3*100 = 510px。
最终宽度 ≈ flex-basis - (收缩比率 * flex-basis) / 收缩总和 * 溢出值
子元素1 = 50 - (1*50 / 510) * 120 ≈ 38.23
子元素2 = 80 - (2*80 / 510) * 120 ≈ 42.35
子元素3 = 100 - (3*100 / 510) * 120 ≈ 29.40
1)简单的网格系统
bootstrap2.3.2 中有个栅格系统,通过百分比或px与float结合产生栅格效果,并且是响应式的,CSS代码要300多行。
flex布局本来就是响应式的,这样会省掉不少代码, 查看在线代码 。
2)多列等高
等高的问题在国外叫《 Holy Grail Layout 》,名称挺高大上的,内容一大堆。
关于等高的技巧,有很多种,可以查看这篇《 八种创建等高列布局 》,方法各有优缺点,无论哪种但实现起来都需要些代码。
而flex布局,设置display=flex,各个子元素再个设置空间,他们的高度能够自动调整到相同, 查看在线源码 。
3)绝对底部
在网页上面,有时候底部那栏需要一直贴在下面,例如友情链接这些信息,而如果中间内容没有,就会塌陷上去。
下图中就是在没有内容的时候上来了,虽然可以在内容区域默认设置个高度,但是底部不会正正好贴到屏幕的最下面,除非精确计算。
国外管这个叫《 Sticky Footer 》
flex布局中只要设置下 flex-direction: column 方向,再设置下容器的高度与屏幕一样或更高,这样底部的子元素就会一直贴在下面。
查看在线代码 。更多的信息可以参考《 Solved by Flexbox 》,Github地址在 这里 。还有个 flexbugs 可以参考参考。
1) 多列布局 中的column-*属性对弹性子元素无效,这也是一种弹性布局,但是有效的场景比较简单
例如瀑布式照片墙(下图所示),需要弹性的内容只有一个img标签
2)曾经有一个场景(下图所示),Flex布局能够等高,但是当用::after设置了个钩后,会出现::after内容的高度还是原先的,导致了错位。
具体内容可以 点击这里查看 。
3) float 和 clear 对弹性子元素无效。
4) vertical-align 对弹性子元素的对齐无效
参考资料:
使用 CSS 弹性盒
Flex 布局教程:语法篇
css3 flex流动自适应响应式布局样式类
Flexbox——快速布局神器
解决Flexbox跨浏览器兼容Bug
flexbox布局的兼容性