弹性方框模型 (Flexible Box Model) 快速入门
简介
我可以肯定,您对于页面上水平或垂直排列的样式元素已经了解得够多了。但是,CSS 还缺少适用于此任务的合适机制。了解 CSS3 弹性方框模型(简称 Flexbox)
该草案将 Flexbox 描述如下:
[...]针对接口设计而优化的 CSS 框模型。除了 CSS 中已有的布局系统之外,该模型还提供了一个额外的布局系统。[CSS21] 在这个新的框模型中,框的子代采用水平或垂直布局,而且可将未使用的空间分配给特定的子代,或者通过“弹性”分配给应展开的子代,在各子代间进行分配。这些框的嵌套(水平嵌套在垂直中,或垂直嵌套在水平中)可用于在两个维度中构建布局。该模型是以 XUL用户界面语言的模型为基础的,适用于多种基于 Mozilla 应用程序(例如 Firefox)的用户界面。
太棒了。对于您这样的开发人员,哦不对,是布局架构师™来说,这意味着什么呢?
- 浮动?说啥呢,我们可不需要浮动。
- 以前具有挑战性的布局是更直观的。
- 我们可以创建真正具有弹性的布局,而浏览器将替我们完成计算工作。
Flexbox 为 display
属性赋予了一个新的值(即 box 值),还为我们提供了 8 个新的属性:
box-orient
box-pack
box-align
box-flex
box-flex-group
box-ordinal-group
box-direction
box-lines
8 个新属性啊?没错,是不是觉得太多了?那好,我们来分别介绍一下。
常用 Flexbox 样式属性
用于框的样式
display: box
- 该显示样式的新值可将此元素及其直系子代加入弹性框模型中。Flexbox 模型只适用于直系子代。
box-orient
- 值:
horizontal
|vertical
|inherit
- 框的子代是如何排列的?还有两个值:
inline-axis
(真正的默认值)和block-axis
,但是它们分别映射到水平和垂直方向。 box-pack
- 值:
start
|end
|center
|justify
- 设置沿
box-orient
轴的框排列方式。因此,如果box-orient
是水平方向,就会选择框的子代的水平排列方式,反之亦然。 box-align
- 值:
start
|end
|center
|baseline
|stretch
- 基本上而言是
box-pack
的同级属性。设置框的子代在框中的排列方式。如果方向是水平的,该属性就会决定垂直排列,反之亦然。
用于框的子代的样式
box-flex
- 值:
0
| 任意整数 - 该子代的弹性比。弹性比为
1
的子代占据父代框的空间是弹性比为2
的同级属性的两倍。其默认值为0
,也就是不具有弹性。
上面的 box-flex-group
、box-ordinal-group
、box-direction
和 box-lines
属性我就不介绍了,因为老实说,您的大部分 Flexbox 作品都未必会用到这些。如果您在使用中想了解这些属性,请访问摘要中的链接。
关于语法的说明:目前,要在 Webkit 和 Gecko 中实施 Flexbox,就必须使用供应商前缀。在本教程中,为了清晰起见,我略去了大部分此类内容。有关详情,请参阅浏览器支持部分。
什么是弹性?
box-flex
样式属性定义了 Flexbox 的子代是弹性还是非弹性的,并且有助于定义该子代相对其同级的弹性比。我们来演示一下这究竟是什么意思。首先,我们从 3 个框开始。
<divid="flexbox"><p>child 1</p><p>child 2</p><p>child 3</p></div>
现在,我们要将它们水平相邻排列,而且无论其中的内容如何都要始终保持同样的高度。目前您会怎样处理这个问题?大部分人可能不假思索地就浮动这些段落,也许向父代添加 overflow:hidden;
以便清除浮动定位。没什么特别的招数。但是利用 Flexbox,我们就能轻松实现同样的目的。
#flexbox { display: box; box-orient: horizontal;}
在上面的代码中,我们只需告知父代根据此 Flexbox 模型进行操作,并沿水平轴排列其所有子代。不用任何浮动。好耶!
子代的宽度仍保留指定值(或者在未指定的情况下保留其固有宽度)。这意味着如果所有子代的总宽度小于父代的总宽度,我们就会得到这样的效果:
默认情况下,Flexbox 的子代仍为非弹性。这可能看起来有点奇怪,但是这样就使得子代有机会加入弹性体验。但是如果您希望第一和第二个子代具有特定宽度,而第三个子代根据父代中的可用空间自行调整宽度,那要怎么做呢?这种情况下就轮到 Flexbox 大显身手了:
#flexbox { display: box; box-orient: horizontal;}#flexbox > p:nth-child(3) { box-flex:1;}
我们将最后一个子代设为弹性的,以占据可用空间。由于我们只对一个元素分配了空间,它将占据所有可用空间。
请注意,该元素只有在框的轴向上是具有弹性的;在本例中,也就是在水平方向上具有弹性。
box-flex 的值是相对值。因此,如果我们将第二和第三个子代设为弹性的:
#flexbox { display: box; box-orient: horizontal;}#flexbox > p:nth-child(2),#flexbox > p:nth-child(3) { box-flex:1;}
它们将各占据同样大小的可用空间,实际上就是平分了可用空间。
现在,我们也可以将 3 个子代的 box-flex
分别设为 1
、2
和 3
,然后它们就会按照这样的比例吸收其父代的多余空间。让我们实际操作看看。
基本示例
查看下面的代码和结果:
悬停在某个框上,查看弹性框的实际效果:当悬停目标展开时,其余的框就会缩小,但是总宽度始终和父代框的大小保持一致。
此处采用的样式其实只有两种:display: box
将内容转为 Flexbox 模式,然后子代的 box-flex: 1
在弹性模式下运行这些内容,从而占据所有额外空间。默认方向为水平,因此 box-orient: horizontal
其实并不是必需的,但是为了表达清晰和便于维护,最好还是加上。默认的 box-align
是弹性的,因此这些 div 占据了其父代框的整个高度。还不错吧?您可以在拉斐尔·戈特 (Raphael Goetter) 制作的这一演示中了解此技术在导航中的应用。
让我们更深入一些。
中央舞台:居中定位
在 CSS 中,将对象在水平和垂直方向上的居中一直以来都是个挑战。在仅限 CSS 的前提下,我们能拿出的最佳解决方案就是 position:absolute; left: 50%; top: 50%;
与等于一半宽度/高度的负左侧/顶部边距相结合。而这只能搭配大小确定的元素。啊!
詹姆斯·约翰·马尔科姆 (James John Malcom) 写道,有一种方法可以根据至少有 6 年历史的 display:table-cell;
(杜桑·亚诺夫斯基 (Dušan Janovský) 曾在 2004 年写过)来垂直对齐。詹姆斯在此记录了完整的水平和垂直解决方案。此方案甚至不需要大小确定的元素即可生效。
借助 Flexbox,我们可以更轻松地实现这一点:
我们并不在子代上设置 box-flex
,因为我们不希望它使用额外空间。我们只希望它无论大小如何都居中。这样做的一大优势在于,我们无需知道明确的尺寸即可将其居中。通常,我们可以使用块或内联对象来完成此操作。就是这么好用。
浏览器支持
那么您现在就能在工作中使用弹性框模型吗?还不行,至少不是对所有浏览器都有效。目前,我们尚未在 IE9 或 Opera 10.60 中实现 Flexbox,但是它曾在 IE9 Platform 的某个预览中出现过,因此微软有可能在未来某个时间添加此功能。
Caniuse.com 列出了当前支持的浏览器,即 Firefox 3 及更高版本、Safari 3 及更高版本以及 Chrome 浏览器。如果您要开发的是移动 Webkit,那么 Flexbox 将是标准布局方案的绝佳替代品。
当然,所有这些仍处于实验阶段,因此您还是应该使用供应商前缀:
/* i wish it was as easy as this: */ display: box; box-orient: horizontal; box-pack: center; box-align: center;
/* but in reality you'll need to do this: */ display:-webkit-box;-webkit-box-orient: horizontal;-webkit-box-pack: center;-webkit-box-align: center; display:-moz-box;-moz-box-orient: horizontal;-moz-box-pack: center;-moz-box-align: center; display: box; box-orient: horizontal; box-pack: center; box-align: center;
如果您觉得这牵涉到很多分类,艾利克斯·拉塞尔 (Alex Russell) 将所有这些选项归纳成了一些实用的帮助类别。
摘要
即使不考虑其他 4 个属性,也已经存在了很多可能性。要进一步了解 Flexbox,请参阅 Isotoma 的 Flexbox 演示和 Mozilla Hacks 上关于 Flexbox 的帖子。W3C Flexbox 规范。开始动手设计些布局吧。尽情体验吧!