本文由大漠根据Chris Mills的《Advanced cross-browser flexbox》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://dev.opera.com/articles/view/advanced-cross-browser-flexbox/,以及作者相关信息
——作者:Chris Mills
——译者:大漠
简介
CSS Flexible盒模型3又简称为Flexbox。摒弃我们传统上使用的一些hack和组件,Flexbox给网络的发展带来了很多正能量和兴奋济,让我们一起把复杂的网站布局变得简易和快速。早前在Flexbox: fast track to layout nirvana?一文中介绍了Flexbox的一些基础知识。在本文中,我将更进一步,借用Modernizr脚本库使用不同的样式做Flexbox在各浏览器下做一些差异化处理,为Flexbox在各浏览器下提供最佳展示水平。
如果你阅读《Flexbox: fast track to layout nirvana?》一文,对英文感觉吃力的话,你可以移动阅读翻译的中文版本《Flexbox——快速布局神器》。
——大漠
推出案例
在这篇文章中创建的例子,看起来如下图所示:
图片最终布局示例。
这个示例包含了多个伸缩容器(flexbox container)。如果你愿意,可以点击示例查看,阅读或探索更详细的代码。
整体布局
示例网站的基本布局是这样的:
<section> <nav></nav> <article></article> <article></article> </section>
<section>设置为一个伸缩容器,代码如下所示:
section { display: -ms-flexbox; -ms-box-orient: horizontal;/*IE10中显不一行,类似于flex-direction:row功能*/ display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: flex; -webkit-flex-flow: row wrap; -moz-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap; }
注:从2011年到Opera和Chrome提供的最新规范,由于IE10目前支持不同的flexbox语法,在IE10中设置特定的属性。Firefox和其他的webkit内核浏览器(如Safari)支持一个更旧版本的flexbox语法(2009),这使用flexbox更糟糕。除此之外,Modernizr报告IE10支持现代flexbox的语法,尽管它他还没有用,因此我们需要使用老的语法来处理IE10下的flexbox效果,而不是使用Modernizr规则来做IE10的兼容。详细的可以看下文,你可以获取更多的细节介绍。
让他们都在同一水平流上,但<nav>使用下面的规则,迫使其在单独的一行中显示:
nav { padding: 1rem; -webkit-flex: 1 100%; -moz-flex: 1 100%; -ms-flex: 1 100%; flex: 1 100%; }
设置“flex-basis”为100%,使用其宽度和父容器的宽度一样,同时迫使其他伸缩项目到新的一行。<article>的“flex-grow”的值设置如下:
article:nth-of-type(1) { -webkit-flex: 2; -moz-flex: 2; -ms-flex: 2; flex: 2; } article:nth-of-type(2) { -webkit-flex: 3; -moz-flex: 3; -ms-flex: 3; flex: 3; }
使他们在主轴点有一定比例的空间——第一个<article>占40%,也就是宽度的五分之二;第二个<article>(也就是图片容器)占60%,也就是宽度的五分之三。这是值得记住——这个比例是只有在同一线上的伸缩项目具有,并非所有伸缩项目都具有的比例。
注:“flex-basis”是一个收缩基准值,首先用在伸缩项目上,在那之后主轴剩余的空间会根据每个伸缩项目的“flex-grow”伸缩比率来划分给每个伸缩项目,分配主轴的剩余空间。当“flex-grow”没有显式的设置值时,它的默认值为“1”。为了更好的了解他是如何工作的原理,你可以阅读flexbox模块中的flex部分,或者阅读《Flexbox——快速布局神器》这篇文章里面有关于flex的内容介绍。
伸缩项目
当你设置了一个元素为伸缩容器的时候,它只会影响他的子元素,而不会进一步的影响他的后代元素。但是没有什么可以阻止你为他们的后代设置为伸缩项目,使用一些布局变得复杂化。很简单,在这里,我把<nav>设置为伸缩容器,我可以让他居中对齐,而且不必担心容器的宽度或视窗的宽度大小。
nav { display: -ms-flexbox; -ms-box-orient: horizontal; -ms-box-pack: center;/*ie10水平居中*/ display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: flex; /*水平居中*/ -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; justify-content: center; }
接着再把<ul>设置为伸缩容器,保证他的子元素li能居中,代码如下所示:
nav ul { text-align: center; display: -ms-flexbox; -ms-box-orient: horizontal; -ms-box-pack: center; display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: flex; -webkit-flex-flow: row wrap; -moz-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap; -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; justify-content: center; width: 80%; } nav a { width: 100%; }
我还添加了一些属性来解决导航菜单项的外观。我希望<ul>不完全拉伸穿过屏幕,并且让所有文本居中显示,所以我设置了一个"width:80%"和"text-align:center"。同时给链接设置了宽度为100%,用来确保链接跨整个列表项宽度。
接下来是神奇的时刻。在这一点上,列表项看起来有眯重叠和奇怪,而用当他们开始包装时看起来有点笨。没有使用媒体查询实现一个响应式的菜单,看上去很酷,那么我们需要下面的代码来实现:
nav ul li { margin: 0 1.5rem; -webkit-flex: auto; -moz-flex: auto; -ms-flex: auto; flex: auto; min-width: 5rem; }
在这里,我给列表项目设置了一个margin,让他们有一定的空间,给他们设置了一个min-width,并且将"flex"设置为“auto”。这是flex的一个特殊的值,可以让伸缩项目具有一个min-width的值,当没有多余的空间的时候,让伸缩项目保持一个常数大小(min-width),但有多余的空间时,伸缩项目能扩大填补。当你扩展和收缩页面的时候看看会发生什么?
接下来设置第二个<article>,并设置里面每个段落(包括段落里的img):
article:nth-of-type(2) { display: -ms-flexbox; -ms-box-orient: horizontal; -ms-box-pack: center; -ms-box-align: center; display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: inline-flex; -webkit-flex-flow: row wrap; -moz-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap; -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; justify-content: center; -webkit-align-items: center; -moz-align-items: center; -ms-align-items: center; align-items: center; -webkit-align-content: flex-start; -moz-align-content: flex-start; -ms-align-content: flex-start; align-content: flex-start; } article p { margin: 0.5rem; -webkit-flex: 1 20rem; -moz-flex: 1 20rem; -ms-flex: 1 20rem; flex: 1 20rem; } article p img { display: block; width: 100%; border: 1px solid black; }
在这里给他们设置了个固定的flex-basis值,所以他们会根据每行的数量增加和减少自己的宽度(如下图所示,没有使用媒体查询),并且会使用每一项,和每一项里面的内容水平垂直居中显示。
一个没有媒体查询的响应式图像框。
Flexbox反馈
支持Flexbox的浏览器有Webkite内核浏览器、Presto-based Opera、Firefox(即将),要真正支持主流浏览器将还需要一段时间。这意味着,如果我们想使用flxbox还需要选择一些备案方法。2009年开始一些浏览器(老的webkit、firefox)支持老版的Flexbox语法。奇怪的是IE10从2011后既支持老的语法又支持新的语法。值得庆幸的是Modernizr脚本库使用“flexbox”和“flexbox-legacy”标记能检测出Flexbox的现代语法和Flexbox旧的语法。实际上它并不支持这两种——它支持一个介于这两者之间的一种语法。这就是为什么我们一直在IE10中把代码写在CSS中,而不是使用Modernizr代码块,你将在后面的文章介绍中可以看到。
注:截至2013年04月会,已经有讨论如何处理Modernizr中Flexbox在IE10中检测问题。
下面的表总结了Flexbox最新语法和2009年、2011年等效的混合语法:
上表显示了不同的flexbox语法支持跨不同的浏览器,对不同属性的等价物。
注:从2009年的规范"box-lines"属性看上去等同于“flex-wrap”,但不幸的是,这个并不支持混合语法的浏览器。
所以,我在示例中添加了以下代码,用来实现支持flexbox混合写法,但不支持flexbox的浏览器的flebox效果:
.no-flexbox section { display: -webkit-box; display: -moz-box; -webkit-box-orient: horizontal; -moz-box-orient: horizontal; } .no-flexbox nav { padding: 1rem; width: 20%; } .no-flexbox article { -webkit-box-flex: 1; -moz-box-flex: 1; } .no-flexbox article p { float: left; } .no-flexbox article img { display: block; width: 200px; }
然后在样式中加入不支持flexbox,甚至不支持混合flexbox语法浏览器的兼容样式代码:
.no-flexbox-legacy nav, .no-flexbox-legacy article { float: left; } .no-flexbox-legacy nav { width: 20%; } .no-flexbox-legacy article { width: 36%; } .no-flexbox article img { float: left; }
注:一个用来生成跨浏览器的flexbox代码,并且可以帮你了解不同浏览器使用语法的在线工具Flexy Boxes。
Flexbox在线生成工具
在70+ 优秀的前端工具中收录了类似于Flexy Boxes在线生成Flexbox的其他工具:
——大漠
添加简单的媒体查询实现宽屏和窄屏的布局
最后,为了解决宽屏和窄屏下的布局,我决定添加几个媒体查询。但注意怎么在媒体查询中添加这些代码,因为Flexbox天生就是创建响应式布局的神器。
首先在支持混合语法上写一些代码来解决响应式效果:
@media all and (max-width: 600px) { h1 { font-size: 5rem; } .no-flexbox section { -webkit-box-orient: vertical; -moz-box-orient: vertical; } .no-flexbox nav { width: 100%; margin-left: -3rem; } .no-flexbox nav a, .no-flexbox nav ul, .no-flexbox nav li { width: 100%; } }
接下来,一个现代flexbox修复,没有在所有的浏览器,在小屏幕宽度。
@media all and (max-width: 480px) { article:nth-of-type(1) { -webkit-flex: 1 100%; -moz-flex: 1 100%; -ms-flex: 1 100%; flex: 1 100%; } body { min-width: 320px; } nav ul { width: 100%; } .no-flexbox-legacy nav, .no-flexbox-legacy article { float: none; } .no-flexbox-legacy nav, .no-flexbox-legacy article { width: 100%; } }
最后用媒体查询给大多少屏幕情况下设置一个居中效果:
@media all and (min-width: 1100px) { section { width: 1100px; margin: 0 auto; } }
总结
此时是有限度的使用Flexbox,当都使用同一种方式支持现代浏览器的时候,Flexbox才会变得更加简易。到现在为止,更有效果的支持,只是一些简单的效果,单行的可以用flexbox,对于多行的在混合语法中就无法得到浏览器的支持。因为它的标准,我的示例运行的很正常,尽管混合语法的flexbox不如现代flexbox布局。另一个有趣的问题是,Firefox好像不支持居中,后来只好使用"margin: 0 auto"来实现(safari下支持居中)。
对于flexbox的一些简单的使用,在现代浏览器(Chrome、Firefox、Safari、Opera Presto 12.1+,IE10+,IOS和Android)可以得到很好的支持。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载烦请注明出处:
英文原文:http://dev.opera.com/articles/view/advanced-cross-browser-flexbox
中文译文:http://www.w3cplus.com/css3/advanced-cross-browser-flexbox.html