视觉顺序与源码顺序:order、z-index 与 reading-flow
Grid 把项从 DOM 顺序里解放出来:order 重排、grid-auto-flow: dense 回填、按网格线任意落位——肉眼所见的顺序于是可以完全偏离源码顺序。项还能重叠(放到同一组单元),此时不必 position,直接用
z-index 决定堆叠。代价是:键盘 Tab 焦点与屏幕阅读器朗读仍沿 DOM 走,与视觉脱节,埋下可达性陷阱。reading-flow / reading-order 正是把顺序焦点导航拨回视觉顺序的新机制。本页用 getBoundingClientRect /
elementFromPoint 与真实 Tab 轨迹实测这三件事。
三种「重排」互不相同。 order 改的是视觉排布(不动 DOM、不影响焦点序);z-index 改的是堆叠(谁盖谁);reading-flow
改的是顺序焦点导航与无障碍树的遍历序。前两者早已可用,第三者是较新的特性(见下方实测)。
1 · order:只动视觉,不动源码顺序
下方 5 个项的 DOM 顺序固定为 1 2 3 4 5。拖动滑块给第三个项设 order:其余项默认 order: 0,引擎先按 order 升序、同值再按 DOM 顺序排布。读数用 getBoundingClientRect 量出真实视觉顺序——而 Tab 焦点与朗读顺序始终是 DOM 的
1 2 3 4 5。
2 · z-index:重叠时谁盖谁(无需 position)
两个项用网格线放到交叠的单元:绿块 grid-area: 1 / 1 / 3 / 3、蓝块 2 / 2 / 4 / 4,在中心格重叠。默认按绘制顺序(后出现的 DOM 在上);给蓝块一个 z-index 即可让它浮起——不必 position: relative,这是 grid(及 flex)项相对普通流的差别。读数用 elementFromPoint 命中重叠处最上层的元素。
3 · reading-flow:把 Tab 焦点拨回视觉顺序
下方 6 个可聚焦按钮的 DOM 顺序是 A B C D E F,但用 order 打乱成视觉的 B D A F C E(逐行从左到右)。把焦点放进网格(点任一按钮)再连按 Tab:reading-flow: normal 下焦点按 DOM 走、与肉眼错位;切到
grid-rows,顺序焦点导航改按视觉行序遍历,与所见一致。下方轨迹实时记录焦点真实经过的按钮。
无障碍准则:视觉顺序应与朗读顺序一致。 用 order / dense / 任意线放置大幅打乱视觉布局时,DOM 顺序仍决定 Tab 与朗读序——最稳妥的做法是让 DOM 顺序本身就贴近视觉与逻辑顺序,把视觉微调留给 grid 放置;确需视觉与 DOM 背离时,再用
reading-flow / reading-order 把焦点序补正。这与 placement 页对 dense 的提醒是同一回事。
4 · 速查:三个「顺序」属性
| 属性 | 作用对象 | 改变什么 |
|---|---|---|
order |
grid / flex 子项 | 仅视觉排布顺序;不动 DOM,不影响 Tab / 朗读序。 |
z-index |
grid / flex 子项(无需 position) | 重叠项的堆叠层级;默认按绘制顺序(后者在上)。 |
reading-flow |
容器 | 顺序焦点导航与无障碍树的遍历序:grid-rows / grid-columns 按视觉行 / 列,grid-order 跟随 order。 |
reading-order |
reading-flow 容器内子项 | 在 reading-flow 之上对单项的遍历序做整数微调(类比 order 之于视觉)。 |
放置与对齐见 基于网格线的放置 与 两轴对齐;跨容器对齐到同一组线见 subgrid 与 display: contents。