这篇文章关于弹性盒子布局,由法国开放网络爱好者 Jérémie Patonnier 撰写。
弹性盒子模型
CSS 3 引入了全新的盒子模型,除了 CSS 1 和 2 中的传统盒子模型。弹性盒子模型决定了盒子在其他盒子内部的分布方式以及它们如何共享可用空间。
您可以查看规范 这里。
这个盒子模型类似于 XUL 使用的盒子模型(Firefox 使用的用户界面语言)。其他一些语言也使用类似的盒子模型,例如 XAML 或 GladeXML。
通常,如果您想创建适应浏览器窗口大小的灵活布局或适应字体大小的弹性布局,弹性盒子模型正是您所需要的。
在这篇文章中,我的所有示例都基于以下 HTML 代码
1
2
3
分布盒子:所以呢?
默认情况下,传统的 CSS 盒子模型根据 HTML 流垂直分布盒子。使用弹性盒子模型,可以显式指定顺序。您甚至可以反转它。要切换到弹性盒子模型,将属性 display
设置为值 box
(或 inline-box
)到具有子盒子的盒子。
display: box;
水平或垂直分布
box-orient
属性允许您指定分布轴。vertical
和 horizontal
值定义了盒子的显示方式。其他值 (inline-axis
和 block-axis
) 具有相同的效果,但还允许您定义基线对齐本身(基本上,盒子被视为“内联”盒子)。
body{
display: box;
box-orient: horizontal;
}
反转分布
box-direction
属性允许您设置盒子出现的顺序。默认情况下,当您只指定分布轴时,盒子会遵循 HTML 流,并在使用垂直轴时从上到下分布,并在使用水平轴时从左到右分布。通过将 box-direction
设置为 reverse
,您可以反转盒子的分布顺序。它就像您实际上反转了 HTML 中元素的顺序。
小心使用此属性,因为它会改变某些其他属性的工作方式,从而产生一些意想不到的行为。
body {
display: box;
box-orient: vertical;
box-direction: reverse;
}
显式分布
box-ordinal-group
属性允许您指定盒子将被分布的顺序。这是最终的定制机会,因为您可以定义所需的顺序,而无需考虑 HTML 流顺序。这些组由从 1 开始的数字定义(这是默认值)。因此,盒子模型将首先分布这些组,然后分布每个组中的所有盒子。分布从最低值(编号为 1 的组)到最高值(编号为 2 及以上的组)进行。
body {
display: box;
box-orient: vertical;
box-direction : reverse;
}
#box1 {
box-ordinal-group: 2;
}
#box2 {
box-ordinal-group: 2;
}
#box3 {
box-ordinal-group: 1;
}
那么灵活度呢?
如果改变自然的 HTML 流顺序是巨大的,那么当您开始处理可用空间时,真正的乐趣就开始了。
盒子大小
默认情况下,盒子不灵活。只有当它具有 box-flex
属性且值为至少 1 时,它才会变得灵活。
如果盒子不灵活,它将尽可能宽以使内容可见,没有任何溢出。它的尺寸可以使用属性 width
和 height
(或它们的 min-*
和 max-*
替代方案)强制执行。
如果盒子是灵活的,它的尺寸将按如下方式计算
- 显式尺寸声明 (
width
,height
,min-*
和max-*
) - 父盒子的尺寸以及所有剩余的可用内部空间。
因此,如果盒子没有尺寸声明,它们的尺寸将完全取决于其父盒子的尺寸。它将按以下方式工作:盒子的尺寸等于其父尺寸乘以其 box-flex
属性的值,再除以其父级中包含的所有盒子的所有 box-flex
属性值的总和。
另一方面,如果一个或多个盒子有显式尺寸语句,则所有这些盒子的尺寸都会被计算,并且所有灵活的盒子都会以与上面相同的原则共享剩余的可用空间。
这听起来可能有点棘手,但通过一些示例,它会变得更容易。
所有盒子都是灵活的
在下一个示例中,盒子 1 是盒子 2 大小的两倍,盒子 2 与盒子 3 的大小相同。它看起来与使用百分比设置盒子的大小相同。但有一个很大的区别。如果您添加一个盒子,您无需重新计算其大小。使用弹性盒子模型,每次添加一个盒子时,所有其他盒子都会自动缩小以腾出空间供新盒子使用。
body {
display: box;
box-orient: horizontal;
}
#box1 {
box-flex: 2;
}
#box2 {
box-flex: 1;
}
#box3 {
box-flex: 1;
}
某些盒子具有固定大小
在下一个示例中,盒子 3 不灵活,宽度为 160 像素。在这种情况下,盒子 1 和 2 可用 240 像素的自由空间。因此,盒子 1 的宽度将为 160 像素(240 像素 x 2/3),盒子 2 的宽度将为 80 像素(240 像素 x 1/3)。如果您愿意,也可以使盒子 3 灵活。在这种情况下,计算此盒子尺寸的方式将几乎与使用 min-width
属性相同。
body {
display: box;
box-orient: horizontal;
width: 400px;
}
#box1 {
box-flex: 2;
}
#box2 {
box-flex: 1;
}
#box3 {
width: 160px;
}
管理溢出
因为我们可以混合灵活盒子、不灵活盒子以及具有预设尺寸的灵活盒子,所以所有盒子尺寸的总和可能大于或小于父盒子尺寸。因此,您可能会有太多空间或空间不足。
我有很多可用空间;我该怎么办?
可用空间的分配取决于属性 box-align
和 box-pack
属性 box-pack
管理水平轴上空间的分配方式,可以有四个可能的值:start
、end
、justify
或 center
start
:所有盒子都在父盒子的左侧,所有剩余的空间都在右侧。end
:所有盒子都在右侧,剩余的空间在左侧justify
:可用空间在每个盒子之间均匀分配center
:可用空间在父盒子的两侧均匀分配
属性 box-align
管理垂直轴上空间的分配方式,可以有五个值:start
、end
、center
、baseline
和 stretch
start
:每个盒子的顶部边缘与父盒子的顶部对齐,所有剩余的空间都放在下方。end
:每个盒子的底部边缘与父盒子的底部对齐,所有剩余的空间都放在上方。center
:可用空间被均匀分配,一半放在上方,一半放在下方。baseline
:所有子级都与其基线对齐放置,剩余的空间根据需要放置在前面或后面(这只是关于此值实际工作方式的简化,但您明白了)。stretch
:每个盒子的高度被调整以适应父盒子高度
关于这些属性如何工作的警告:它们受到 box-orient
和 box-direction
属性使用的强烈影响。它们会导致一些意想不到的行为(例如,值 start
和 end
的行为可能会完全颠倒)。我希望一旦规范最终确定,我们将获得更多关于这些属性如何协同工作的信息。
body {
display: box;
box-orient: horizontal;
/* The content of the body is horizontally centered */
box-pack: center;
/* and vertically as well ... o/ */
box-align: center;
width: 100%;
height : 100%;
}
如果空间不足会发生什么?
就像传统的盒子模型一样,溢出属性允许您定义管理它的方式。这里没有惊喜。
但是,您在这里也要小心。事实上,box-orient
和 box-direction
属性的使用可能会弄乱它。例如,您可以看到元素溢出到右侧而不是左侧,或溢出到顶部而不是底部。在尝试将其用于大型项目之前,花点时间进行实验,否则您可能会疯掉。
您还可以通过将 box-lines
属性设置为 multiple
来避免溢出,使盒子跨多行(或列,具体取决于方向)运行。
好吧,很酷,但它在现实生活中有效吗?
是的!Gecko 和 WebKit 都有盒子模型的供应商前缀实现 (注意:规范的当前状态不反映 Mozilla 或 WebKit 的实现)。这意味着 Firefox、Safari、Chrome 以及使用其中一个渲染引擎的任何浏览器都能够使用本文中描述的功能。如果您使用这些很棒的浏览器之一,这里有一个关于弹性盒子模型实际操作的小演示。
如果您没有使用实现盒子模型的浏览器,则此屏幕截图显示了它的样子
总结
您可以开始使用此盒子模型来使用现代 Web 浏览器布局您的 HTML 文档。但要小心,这是 W3C 工作草案的第一个迭代。肯定会有一些变化。无论如何,Gecko 和 Webkit 中可用的实现非常一致且成熟,因此如果存在更改,它们应该不会那么麻烦。
这个盒子模型是一种非常简单易行的方法,可以解决网页设计中的一些常见问题(表单布局、页面页脚、垂直居中、视觉流与 HTML 流分离等)。我强烈建议您熟悉它,因为它可能会在不久的将来成为网页设计师的标准工具(如果微软决定将其包含在 IE 中,它可能会变得非常快)。
目前已有的功能是一个很好的开始,可以用来玩玩。但到目前为止,传统盒子模型和弹性盒子模型的交互方式并不十分清楚(例如,不可能在使用 box-ordinal-group
属性的盒子中使用 position:relative
与属性 left
或 top
)。这将得到改进,但不要惊讶,如果您的工作习惯受到一定程度的破坏。另一个棘手的点:与这个新的盒子模型相关的属性的交互方式有时会非常令人困惑。这应该让您想起您发现 float
属性的那一天。;)
更多信息
- Shawn J. Goff:CSS3 弹性盒子布局模块
- CSS3.info:介绍弹性盒子布局模块
- W3C:弹性盒子布局模块
关于 Paul Rouget
Paul 是一位 Firefox 开发者。
105 条评论