的Markdown貌似不支持插入iframe,所以文章里的JSFiddle示例都改做截图了,如果有需要可以点击下面的链接,到众成查看,英文版链接一并附上。
译者:kangflict(飞扬)
链接:http://www.zcfy.cc/article/966
原文:https://bocoup.com/weblog/dive-into-flexbox
简介
Flexbox 是 CSS3 中提出的新布局模型,用于适应现代网络开发中日益复杂的布局需求。 近来,Flexbox 的语法逐渐稳定下来,本文来为大家揭开它的神秘面纱,并盘点其技术细节。浏览器支持将会快速增长,因此当对 Flexbox 的支持足够广泛以至达到实用水平时,你将会在这场游戏当中拔得头筹。如果想要了解它的工作方式和原理,那么就继续读下去吧!
为什么需要 Flexbox?
长期以来,人们使用 table、float、inline-block 以及其他 CSS 特性来对站点内容进行布局。然而,这些工具没有一个是为当前的复杂网页或网络应用设计的。像垂直居中这样的简单的需求都需要费点儿力气才能满足,以至于我们通常认为单枪匹马实现灵活栅格布局这样的需求不太现实,因此各种 CSS 栅格布局框架获得了巨大的成功。
规范进展与浏览器支持
Flexbox 规范的相关工作已经进行 3 年之久,很多浏览器厂商都发布了其实验性质的实现。2012 年 9 月,针对 Flexbox 语法的第三次主要修订进入了 W3C 的候选推荐阶段。这说明 W3C 对当前的语法是满意的,并鼓励浏览器厂商进行实现。
Flexbox 规范大事年表:
- 2009 年 7 月,工作草案(display: box;)
- 2011 年 3 月,工作草案(display: flexbox;)
- 2011 年 11 月,工作草案(display: flexbox;)
- 2012 年 3 月,工作草案(display: flexbox;)
- 2012 年 6 月,工作草案(display: flex;)
- 2012 年 9 月,候选推荐(display: flexe;)
各个浏览器都在积极地接纳 Flexbox。本文写就之时,Chrome 22+、Opera 12.1+ 以及 Opera Mobile 12.1+ 均已支持 Flexbox。Firefox 18 和 Blackberry 10 也将马上跟进。我建议使用支持 Flexbox 的浏览器来阅读本文,以便观察示例如何工作。
相关概念和术语
尽管在 Flexbox 的帮助下,以前千辛万苦才能实现或者根本不敢想象的布局都能轻而易举地实现,但要真正习惯以 Flexbox 的方式进行布局还是需要一定的时间。在使用 Flexbox 时,新的术语或概念都可能成为拦路虎,因此我们先来讨论一下术语和概念的问题。
Flexbox 布局涉及 Flex 容器(Flex Container)和 Flex 项目(Flex Item)。Flex 容器的 display
属性为 flex
或 flexbox
。flex
属性使得容器渲染为块级元素,而 inline-flex
则使其渲染为行内元素。
下面是声明 Flex 容器的示例:
.flex-container {
display: -webkit-flex;
display: flex;
}
本文中的所有代码示例都将包含全面的浏览器厂商前缀。
Flex 容器的任何子元素都是 Flex 项目,并且 Flex 项目可以有任意多个。Flex 容器之外的任何元素以及 Flex 项目内的元素都将照常渲染。简而言之,Flex 容器决定 Flex 项目在其内部的布局方式。
Flex 布局线(Flex Line)
在Flex容器内,Flex 项目沿 Flex 布局线 排布。默认情况下,每个容器只有一条 Flex 布局线。
上图的示例展示了默认情况下两个项目在容器中的排布:从左到右,沿水平 Flex 布局线排列。
书写模式(Writing Modes)
使用 Flexbox 进行富有创造性的布局不可避免地要改变 Flex 布局线的方向。默认情况下,Flex 布局线与文本书写方向一致:从左到右,从上到下。
W3C 有一个工作草案,是关于一项称作书写模式(Writing Modes)的新特性的。书写模式为从右至左或纵向的文字排布提供了新的实现方式,在对特定的语言进行排版时常会遇到这样的需求。
书写模式仍然处于半成品状态,不过 direction
属性已经在 Chrome 中得到了支持。上面的示例中,如果如果我们将 direction
的值设置为 rtl
(从右到左),那么不光文本内容会从右往左渲染,Flex 布局线的方向也会改变,从而影响页面的布局。
这或许就是很多与 Flexbox 相关的术语非常抽象的原因。如果不能确定页面语言的话,我们就不能简单地用“上”“下”“左”“右”来代表布局方向。
主轴与侧轴(Main Axis and the Cross Axis)
Flexbox 通过引入概念主轴(Main Axis)和侧轴(Cross Axis)来体现对书写模式的支持。Flex 布局线与主轴的方向一致,而侧轴则与主轴正交。
每条轴的起点、终点以及方向的名字如下所示:
- 主轴起点(Main Start)
- 主轴终点(Main End)
- 主轴方向(Main Direction,有时也称作流方向,即 Flow Direction)
- 侧轴起点(Cross Start)
- 侧轴终点(Cross End)
- 侧轴方向 (Cross Direction)
主轴和侧轴两个术语非常重要,我们有必要在继续之前将其彻底搞懂。在使用 Flexbox 进行布局的时候,任何东西都与此有关。本文所有的示例中,书写模式都是从左往右从上往下的,但是我们必须了解并不一定所有情况下都是如此。
Flex 容器之属性
flex-direction
flex-direction
能够改变 Flex 容器的轴向。flex-direction
的默认值为 row
,即按照 writing-mode
的方向对 Flex 项目进行排布,默认情况下从左到右,从上往下。其他可能的值如下:
- row-reverse:主轴起点和终点对换。如果书写模式(writing-mode)从左往右,那么此时 Flex 项目会由右往左进行排布;
- column:主轴与侧轴对换。如果书写系统为水平方向的,那么 Flex 项目将沿纵向排布;
- column-reverse:与column的效果相同,只是轴向翻转。
将前面示例中的 flex-direction
值改为 column
。
现在,Flex 项目变为纵向排列的了。
justify-content
Flex 容器的 justify-content
属性用于控制 Flex 项目在主轴上的位置。可能的值有:
- flex-start(默认值)
- flex-end
- center
- space-between
- space-around
将 justify-content
的值设置为 center
能够让 Flex 项目沿主轴居中:
flex-start
、flex-end
以及 center
的含义相当直截,但是 space-between
和 space-around
这两个用于确定 Flex 项目间留白的属性值的含义就不那么明显了。下面这张来自规范的示意图对各个属性值做出了最佳诠释:
align-items
align-items
是对 justify-content
的补充,它确定的是 Flex 项目在侧轴上的位置。可能的取值有:
- flex-start(默认值)
- flex-end
- center
- baseline
- stretch
我们将 align-items
的值设置为 center
,从而让 Flex 项目在侧轴居中排布:
flex-start
、flex-end
和 center
的含义仍旧直截了当,strech
也相当简单:让 Flex 项目充满从侧轴起点到侧轴终点的所有空间。baseline
则使得 Flex 项目沿基线对齐。基线是由 Flex 项目的内容计算得出的。下面出自 Flexbox 规范的示意图对此做出了最佳阐释:
flex-wrap
到现在为止,每个 Flex 容器都只有一条 Flex 布局线,利用 flex-wrap
属性,就可以得到有多条 Flex 布局线的的容器。flex-wrap
可选的值如下:
- nowrap(默认值)
- wrap
- wrap-reverse
如果 flex-wrap
的值为 wrap
,那么当一条 Flex 布局线无法容纳所有 Flex 项目时,多余的项目就会折转到附加的 Flex 布局线上。新添的 Flex 布局线沿侧轴的方向排列。
这里有一个使用 flex-wrap
的示例:
wrap-reverse
的效果与 wrap
相同,只是 Flex 布局线将沿与侧轴相反的方向添加。
align-content
align-content
能够影响 flex-wrap
的行为。它与 align-items
类似,但是并不是用于对齐 Flex 项目,而是用于对齐 Flex 布局线。正如你所想,它们可能的取值也非常相似:
- stretch(默认值)
- flex-start
- flex-end
- center
- space-between
- space-around
这些值的效果与它们在 align-items
中的表亲基本相同。
这里,我们将 align-content
设为 center
:
flex-flow
flex-flow
是 flex-direction
和 flex-wrap
的简写:
flex-flow: [flex-direction] [flex-wrap]
例如:
gistfile1.css
.flex-container {
-webkit-flex-flow: column nowrap;
flex-flow: column nowrap;
}
Flex 项目之属性
Flex 项目是 Flex 容器的直接子元素,Flex 容器中的文字段落也会被当做 Flex 项目处理。
Flex 项目的内容则会照常渲染。例如,float
属性对 Flex 项目不起作用,但是 Flex 项目内部却可以存在浮动元素。
我们称 Flex 项目有主轴尺寸和侧轴尺寸。主轴尺寸是 Flex 项目在主轴方向上的尺寸,侧轴尺寸则是 Flex 项目在侧轴方向上的尺寸。事实上,通常 Flex 项目的宽和高分别就是它的主轴尺寸和侧轴尺寸,不过这取决于 Flex 容器的轴的设置。
下面的属性能够影响 Flex 项目的行为。
order
order
最为简单,它控制着 Flex 项目的渲染顺序。本例中,我们将一个 Flex 项目的 order
属性设置为 -1
,从而使其显示在所有其他元素之前。
这对可访问性来说可能非常有用,因为有时我们需要文档结构和页面展示以不同的顺序出现。
margin
你或许已经对 margin: auto;
在通常情况下的效果非常熟悉了。在 Flexbox 的世界里,它仍然发挥着相似的作用,只不过更加的强大。“自动”边距能够吸收掉多余的空白,从而将 Flex 项目推到不同的位置上去。
这里,我们为第一个 Flex 项目设定 margin-right: auto;
,从而使得该项目右边所有多余的空白都被吸收掉:
接着,我们使用 margin: auto;
来摘取 CSS 排版的圣杯:真正的垂直居中!
align-self
Flex 项目的 align-self
属性能够覆盖 Flex 容器为其指定的 align-items
属性。两个属性具有相同的取值范围:
- stretch(默认)
- flex-start
- flex-end
- center
- baseline
此例中,我们为每个 Flex 项目指定了不同的 align-self
值:
上例中有两个 Flex 项目的 align-items
值为 baseline
,这是因为 baseline
项目是以彼此为参照来进行对齐的。
flex
终于到 Flexbox 中的 flex
属性了。flex
确定了 Flex 项目在主轴剩余空间排布时的策略。
让我们来逐一过目 flex
的常见取值:
flex: [数字]
该语法通过指定一个数字,来确定当前 Flex 项目占主轴剩余空间的比例。
本例中,第一个 Flex 项目占剩余空间的 2/4,其余两个 Flex 项目各占 1/4:
将每个项目的 flex
属性都设置为 1 是一项非常有用的技巧,此时主轴剩余空间将被平均分配给各个 Flex 项目。
flex: initial
flex
属性为 initial
的项目将会失去弹性伸缩能力,但是在必要的时候仍然能够缩小(被挤小)。
flex: auto
flex
属性为 auto
的项目拥有在主轴上进行弹性伸缩的所有能力。
目前,Opera 12.11 能够支持 auto
,但是 Chrome 23.0.1271.95 还不可以。实际上,我们只需要使用 flex: 1
就可以绕过这个问题。
flex: none
flex
属性为 none
的项目在任何情况下都不具备弹性伸缩的能力。
flex 进阶
事实上,flex
是 flex-grow
、flex-shrink
和 flex-basis
的简写:
flex: [flex-grow] [flex-shrink] [flex-basis]
不过,多数情况下我们都不需要这样写,它需要对 flex 背后的算法更为精深的理解。如果你觉得自己是真正的猛士,看这里的规范。
我们也可以为 flex-grow
、flew-shrink
以及 flex-basis
分别指定属性值。但是我强烈建议你不要这样做,因为当使用 flex
简写形式时,浏览器会为没有值的属性指定更有意义的默认值。
visibility
如果有实现支持的话,对于 Flex 项目,visibility: collapse;
应当表现得与 visibility: hidden;
和 display: none;
不同。具有该属性的 Flex 项目将会影响所在 Flex 容器的侧轴尺寸,但是并不占据主轴方向的空间,也不可见。这对动态添加移除 Flex 项目非常有用,同时也不影响 Flex 容器的侧轴尺寸。
目前,visibility: collapse;
貌似在任何浏览器上都没有得到正确的支持。当前的实现中,visibility: collapse;
的行为看上去与 visibility: hidden;
相同。我期待这种情况赶紧得以改观。
这里有一个还不错的 collapse
模拟实现,能够让你看到规范中 collapse
是如何工作的。
总结
如你所见,Flexbox 是一种强大的新式布局工具,将从根本上变革我们现有的网站布局手段。亦如所见,它需要我们使用全新的思考方式来进行布局。我希望这篇文章能够在你开始使用 Flexbox 对网站进行布局时帮你一把。不知道你信不信,反正我是看到了光明的未来。