第 3 课:flex-direction 与主轴的转向
本课目标:
- 说出
flex-direction做什么,并列出它的四个值。- 解释为什么
justify-content不是“水平属性”。- 预测主轴变成竖列后,哪个属性负责上下移动 item。
先修条件:第 2 课(
justify-content= 主轴,align-items= 交叉轴) | 上一篇 << 02 | 下一篇 04 >>
“justify-content = 水平方向”失灵的那一刻
第 2 课里你学到 justify-content 左右移动 item。这没错,直到它出错。你把 item 竖着排成一列的那一瞬间,justify-content 开始上下移动它们;如果你把它背成了“管水平的那个”,你现在就在和自己的布局较劲。始终学不顺 Flexbox 的人,多半是按属性的默认方向去记它们,而不是按轴去记。这一课把“水平”换成那个真正成立、而且永远不变的说法。
讲解
flex-direction 设定 flex item 在容器里的摆放方式,它定义主轴以及 item 流动的方向1。它有四个值,默认是 row1:
row(默认):主轴沿行的方向,从左到右,就是你已经熟悉的水平方向。row-reverse:同一条轴,但 item 从右边开始排。column:主轴改为从上到下,沿块的方向2。column-reverse:同一条垂直轴,item 从底部开始排。
不变的规则在这里:justify-content 永远跟着主轴,align-items 永远跟着交叉轴。flex-direction 决定主轴指向哪里,也就决定了这两个属性各自实际做什么。属性本身没有任何变化,只是它们钉在的那条轴转了方向。
从上往下读这张图:flex-direction 是开关。选 row,主轴水平,于是 justify-content 管水平。选 column,主轴垂直,于是同一个 justify-content 变成管垂直。属性没变,只是它骑着的那条轴转了九十度。
这也是为什么竖直菜单和侧边栏在 Flexbox 里非常自然:设 flex-direction: column,item 就竖着排,然后 justify-content 在垂直方向拉开间距,align-items 负责它们的左右对齐。还是那两个属性,只是轴转了。
是起点和终点,不是左和右
这就是为什么整门课一直说“主轴起点”而不说“左边”。Flexbox 对文档的书写模式不作任何假设2。在英文环境下写 flex-direction: row,主轴的起始边在左、结束边在右;但换成从右往左书写的阿拉伯语,主轴的起始边就在右边、结束边在左边2。CSS 一个字都没改,是这条轴的起点挪了位置。
这才是 flex-start 和 flex-end 真正命名的东西:一条轴的起始线和结束线,按文档的书写方向去解析2。在上面英文和阿拉伯语这两种情况里,交叉轴都仍然从顶部开始、到底部结束,因为两者都是横向书写模式2。裸的 start 和 end 这两个值同样是书写模式感知的3。
实践上:如果你写了 justify-content: flex-end,item 却落在了你没想到的那一侧,先查书写方向,再怀疑属性。row 和 row-reverse 这两个值会受 flex 容器方向性的影响——在从右往左的方向下,row 是从右往左走,row-reverse 反而从左往右走1。
-reverse 到底反转了什么
row-reverse 和 column-reverse 并不动轴的方向,它们交换的是哪一端算主轴起点1。于是 item 从相反的那一端开始排,视觉顺序也整体反过来。这确实有用——但它有一个代价,值得在你伸手去用之前就知道。
用 row-reverse 或 column-reverse 会让屏幕上的视觉顺序和标记里的 DOM 顺序脱节。屏幕阅读器用户跟的是 DOM 顺序,所以他们接收到的内容次序和视力正常的用户看到的不一样,这会实实在在损害依赖辅助技术导航的人的体验1。如果这个视觉顺序是承载含义的,就去改 HTML 的顺序,而不要用 CSS 反转。
读别人代码时还有一个简写值得认得:flex-flow 把 flex-direction 和 flex-wrap 合成一条声明,所以 flex-flow: row wrap 一次设定两者2。换行那一半由第 5 课负责。
完整示例(跟着做)
一个竖直侧边导航,上下均匀分布,每个链接左右居中:
用规则走一遍。flex-direction: column 让主轴变垂直。justify-content: space-between 作用在主轴上,所以它把链接沿垂直方向拉开:第一个在顶部,最后一个在底部,间距均匀。align-items: center 作用在交叉轴上,交叉轴现在是水平的,所以每个链接左右居中。如果你原本指望 justify-content 水平分布它们,column 这一翻转正是会让你意外的地方。
你来试试(填空示例)
你想让三个按钮竖着堆叠,并钉在一个高容器的底部。填上两行:
答案:flex-direction: column(主轴变垂直)和 justify-content: flex-end(主轴终点现在是底部)。因为主轴指向下方,flex-end 就是底部,而沿这条轴移动的属性正是 justify-content。把它读成“哪条轴、哪一端”,column 翻转就不再是陷阱。
小结 + 下节课预告
flex-direction 决定主轴指向哪里;justify-content 跟着主轴,align-items 跟着交叉轴,无论它们指向何方。用“主轴/交叉轴”换掉“水平/垂直”,column 翻转就不再让你吃惊。到目前为止,每个 item 都按自己的自然尺寸占位。下一课我们让 item 分享剩余空间,flex-grow、flex-shrink、flex-basis 就在那里登场,而所有误解里最大的那一个也在那里:flex: 1 到底在分什么。
Footnotes
-
MDN: flex-direction — https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/flex-direction ↩ ↩2 ↩3 ↩4 ↩5
-
MDN: Basic concepts of flexbox — https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Flexible_box_layout/Basic_concepts ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
MDN: Aligning items in a flex container — https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Flexible_box_layout/Aligning_items ↩
Exercises
在刷新之前,先预测 align-items: flex-end 在 flex-direction: column 的容器里会做什么。然后验证。
第 2 级(进阶)My note
Jot down thoughts, sticking points, things you didn't get. Written to this course's appendix only — the lesson file is never touched.