浏览器兼容性问题,是前端工程师的一个必然要遇到的事情。今天我们来聊聊flexbox 的兼容问题,PC端大家都看到了http://caniuse.com/#search=flex 除了IE支持都很好,但到了移动端就惨不忍睹了(特别是国产手机)。其主要原因还是国产浏览器厂商的更新和支持更不上国际速度,还拿着09年的标准来糊弄自然会有问题。很多人不敢用flexbox说它在国产手机里支持不好云云,其实主要原因还是,我们对其在定制过程中的各个版本规范搞不清状况。好了我们来看看吧:
注:对于IE,我们兼容到10
历史
09年到现在flexbox分别经历了三种方式:display:box;
、display:flexbox
还有现在的display:flex;
If you Google around about Flexbox, you will find lots of outdated information. Here’s how you can quickly tell:
- If you are looking at a blog post (or whatever) about Flexbox and you see display: box; or a property that is box-{*}, you are looking at the old 2009 version of Flexbox.
- If you are looking at a blog post (or whatever) about Flexbox and you see display: flexbox; or the flex() function, you are looking at an awkward tweener phase in 2011.
- If you are looking at a blog post (or whatever) about Flexbox and you see display: flex; and flex-{*} properties, you are looking at the current (as of this writing) specification.
flexbox最初定义的时候其实2009年定义了第一个版本以后,就有浏览器厂商率先实现了display:box
的功能。到了2011年大家对原来实现的功能还不满意,为了不改变原来对display:box
的支持,就有了display:flexbox;
。到后来规范逐渐成熟再加上功能需要在加完善,所以就到了display:flex
,还会不会改鬼知道呢。
支持情况
我们从caniuse上看一下支持度。
display:box;
除了Firefox其他的都partial support with prefix-webkit-
display:flexbox
支持也很好啊。display:flex
发现差不多和上一个一样的支持度。
大体总结了一下,除了Opera mobile12,还有IE,各大浏览器都是支持flexbox的旧版语法的。
注:最新的语法才加入了wrap的属性,所以旧版肯定是不支持的
解决方案
从上面的调研可以看出,其实最新的flex是兼容之前的语法的,只不过有一些新增的语法。那么解决这样的兼容问题显而易见的就是增加上旧版的语法,就可以解决一些支持旧版语法的浏览器啦。
第一篇我们说到,flexbox分为container和item,所以兼容的写法也分两部分。
container1
2
3
4
5
6
.grid{
display: -webkit-box; /* Chrome 4+, Safari 3.1, iOS Safari 3.2+ */
display: -webkit-flex; /* Chrome 21+, Safari 6.1+, iOS Safari 7+, Opera 15/16 */
display: flex; /* Chrome 29+, Firefox 22+, IE 11+, Opera 12.1/17/18, Android 4.4+ */
}
item
1 |
|
看到这里,你可能就有疑问,这样每次写这么多前缀不累吗?我们有工具啊:
我们可以使用类似autoprefixer, 或者是sass\less等工具来写css。另外安利一个sass的mixin大家可以看看compass-flex。
还有一种方式就是,完全用老版本的display:box
来写,这样的话 除了一些新特性比如flex-wrap不能用以外(如果你觉得没必要用新特性)别的基本没什么问题,这里贴一份朋友写的grid系统 (据说兼容Android2.3):
1 | .row { |
其他的不兼容特性
- 在旧版的规范中,使用比例伸缩布局时,子元素的内容长短不同会导致无法“等分”,这个时候,我们需要给子元素设置一个“width:0%”来解决问题
- 不要给item设置“margin:auto”的属性,在部分安卓机下,它会导致该元素的宽度撑开到100%占位
- 旧版的box item要求属性是块级结构,所以很多inline元素需要设置display:block等才能显示正常
- text-overflow: ellipsis;在display:flex元素上无效
记住上面的坑,避免跳进去。
方法论
其实兼容性的解决办法是有一套方法论的。我个人觉得做到以下几点是必要的:
- 确定业务需求面向的运行环境是怎样的,需要兼容哪些浏览器;
- 查改特性的兼容性,兼容到了哪个版本,该不该用这个属性,或者给出兼容的写法;
- 学会使用工具;
- 充分测试,把兼容问题当做一种自我积累和提升积极面对,不断完善。
好了就这么多,上面的坑的列表大家可以补充,欢迎关注我的专栏知乎前端杂货铺