摘要

  • W3C 2009 年 7 月 23 日公布的首份 Flexible Box Layout 工作草案,让盒子里的元素在有空位时扩张、空间不足时收缩;当时的属性包括 box-flex。
  • 2012 年 9 月 18 日的候选建议使用 display: flex 和增长、收缩、基础尺寸规则。2018 年 11 月 19 日的候选建议强调:改变屏幕上的排列,不会顺手改掉文档、朗读或键盘导航的顺序。

工具栏有三个孩子,住的房子却会随着窗口宽度伸缩。搜索框想舒展身体,长名字按钮坚持每个字都要坐下,第三个按钮原本安分,直到墙壁向里挤。固定宽度的家具摆法常常在窄屏前露出窘态。Flexbox 把分房规则写进布局,让父容器说清谁能长、谁要缩、走哪条轴、剩余空位放在哪儿。家庭会议没有变得温柔,至少有了账本。

W3C 在 2009 年 7 月 23 日发布的首份 Flexible Box Layout 工作草案着眼于界面。盒子里的孩子可以横排,也可以竖排。可伸缩的孩子能拿走剩余空间,房间变小时也能收缩。草案说明这一模型受到 XUL 界面盒子模式启发。那时的 CSS 词汇是 display: box、box-orient、box-flex、box-lines。这些名字属于早期文本,不能把旧例子原封不动地当作今天的写法。

box-flex 表示相对伸缩能力。数值为二的孩子可以比数值为一的孩子分到更多余量,但这并非谁喊得响谁赢。一个孩子碰到最大宽度,就得停下来,剩余空间交给兄弟姐妹。内容本身的尺寸、最小与最大限制也参与结算。父容器提供房间,孩子们在约束内分配。对宽度反复变化的工具栏来说,这比把三件家具钉死在地板上有用得多。

2012 年 9 月 18 日的 W3C 候选建议重整了规则。display: flex 与 inline-flex 定义容器;元素沿主轴排队,另有交叉轴。flex 简写把基础尺寸、增长因子和收缩因子放在一起:先占多少地方,房间宽了拿多少,房间窄了让多少。搜索框可以吞下多出来的横向空间,菜单按钮则保住可用的尺寸。窗口缩小时,浏览器重新计算分配,而不是任由一列固定宽度按钮冲出边框。

“分配”有具体算法。正的空闲空间按增长因子参与分配;地方不够时,收缩因子、原始尺寸和限制共同决定结果。增长因子二,并不保证最后宽度永远是邻居的两倍。关键是容器宽度变化时,谁承担变化。作者把这层关系写进 CSS,浏览器在每次排版时重新算。按钮终于不用靠运气等一个刚刚好的窗口宽度。

空位还有方向。工具栏可以从一端排向另一端,也可以竖着叠。允许换行时,挤不下的孩子走到下一行;对齐规则决定它们沿两条轴怎样站。横向盒子套进纵向盒子,可以搭出更复杂的界面。每个弹性容器却先解决自己的主轴分配。这是这篇故事的核心,与先规划行列位置的 CSS Grid 不是同一个问题。

孩子们随后发现可以偷偷换座位。2012 年文本里的 order 能改变元素的视觉排列。规范同时指出另一条路仍按原位走:语音与默认的顺序导航仍跟随文档源顺序。屏幕上第一个按钮,键盘焦点可能要经过几个兄弟才轮到它。鼠标用户看着一张座位表,键盘用户走着另一张。调整画面并没有自动改写邀请名单。

2018 年 11 月 19 日的 W3C 候选建议把这一点说得更明白:order 与反向排列用于视觉呈现,不能代替正确的源顺序。文本还补足了余量分配的细节:增长值小于一时,正的空位可以留下未分配部分。“弹性”不保证吞光最后一个像素。工具栏末尾若还空着一截,可能正是浏览器严格照章办事。

内容一变,旧账又要重算。某个按钮翻译成另一种语言,标签更长;另一个按钮有最小宽度,死活不再让位;窄屏让一部分元素换了行。Flexbox 会按照规则响应,自己却不知道哪个操作对读者更重要。团队还得决定哪些控件应先出现、哪些必须保持可点,之后再选择基础尺寸、因子与对齐。可伸缩不是“随它去”的许可证。

Flexbox 让父容器成为可变空间的分账人。孩子们依照声明的份额与限制伸缩,浏览器在窗口变化时重新结算。作者仍要先排好有意义的文档顺序,再让布局负责宽窄。按钮之间可以谈分房;读者不该在屏幕和键盘两张地图之间谈判。