发布时间:2025 年 5 月 1 日
CSS reading-flow
和 reading-order
属性从 Chrome 137 开始提供。本文介绍了这些属性的设计背后的原因,以及一些简要详细信息,以帮助您开始使用这些属性。
网格和 flex 等布局方法彻底改变了前端开发,但它们的灵活性可能会给某些用户带来问题。很容易出现视觉顺序与 DOM 树中的源顺序不一致的情况。由于浏览器会遵循此来源顺序,因此如果您使用键盘浏览网站,部分用户可能会在浏览网页时遇到意外跳转。
我们设计并添加了 reading-flow
和 reading-order
属性到 CSS 显示规范中,以尝试解决这个长期存在的问题。
reading-flow
reading-flow
CSS 属性用于控制 Flex、网格或块布局中的元素向无障碍功能工具显示的顺序,以及使用线性顺序导航方法将焦点移至这些元素的方式。
它接受一个关键字值,默认值为 normal
,用于保持按 DOM 顺序排列元素的行为。如需在 flex 容器中使用它,请将其值设为 flex-visual
或 flex-flow
。如需在网格容器中使用它,请将其值设为 grid-rows
、grid-columns
或 grid-order
。
reading-order
借助 reading-order
CSS 属性,您可以手动替换阅读流容器中内容的顺序。如需在网格、Flex 或块容器中使用此属性,请将容器上的 reading-flow
值设置为 source-order
,并将各个项的 reading-order
设置为整数值。
Flexbox 中的示例
例如,您可能有一个 Flex 布局容器,其中包含三个元素,并且这些元素的排列顺序是从上到下,而您还想使用 order 属性重新排列该顺序。
<div class="box">
<a href="#">One</a>
<a href="#">Two</a>
<a href="#">Three</a>
</div>
.box {
display: flex;
flex-direction: row-reverse;
}
.box :nth-child(1) {
order: 2;
}
您可以尝试使用 TAB 键查找下一个可聚焦元素,使用 TAB+SHIFT 键查找上一个可聚焦元素,以便在这些元素之间导航。这遵循来源顺序:One、Two、Three。
从最终用户的角度来看,这没有意义,而且可能会造成很大的困惑。如果我们使用无障碍空间导航工具在页面中导航,也会发生同样的情况。
如需解决此问题,请设置 reading-flow
属性:
.box {
reading-flow: flex-visual;
}
焦点顺序现在为:一、三、二。这与您从左到右阅读英语时获得的视觉顺序相同。
相反,如果您希望保持原始焦点顺序(即按相反顺序),可以设置:
.box {
reading-flow: flex-flow;
}
焦点顺序现在是相反的 flex 顺序:Two、Three、One。在这两种情况下,系统都会考虑 CSS order
属性。
网格布局示例
如需了解此功能在网格中的运作方式,假设您要创建一个布局,其中包含 12 个可聚焦区域的 CSS 网格自动放置项。
<div class="wrapper">
<a href="#">One</a>
<a href="#">Two</a>
<a href="#">Three</a>
<a href="#">Four</a>
<a href="#">Five</a>
<a href="#">Six</a>
<a href="#">Seven</a>
<a href="#">Eight</a>
<a href="#">Nine</a>
<a href="#">Ten</a>
<a href="#">Eleven</a>
<a href="#">Twelve</a>
</div>
您希望第五个子项占据最顶部的最大空间,其次是位于网格中间的第二个子项。所有其他子项都可以按照列模板自动放置在网格中。
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
}
.wrapper a:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper a:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
尝试使用 Tab 键查找下一个可聚焦元素,使用 Tab+Shift 键查找上一个可聚焦元素。此属性遵循来源顺序:一到十二。
如需解决此问题,请设置 reading-flow
属性:
.wrapper {
reading-flow: grid-rows;
}
焦点顺序现为:五、一、三、二、四、六、七、八、九、十、十一、十二。它遵循视觉顺序,逐行显示。
如果您想让阅读流程遵循列顺序,则可以改用 grid-columns
关键字值。然后,焦点顺序将变为 5、6、9、7、10、1、2、11、3、4、8、12。
.wrapper {
reading-flow: grid-columns;
}
您也可以尝试使用 grid-order
。焦点顺序保持为 1 到 12。这是因为没有为任何商品设置 CSS 订单。
使用 reading-order
的块容器
借助 reading-order
属性,您可以指定应在阅读流程中何时访问某个项,从而替换 reading-flow
属性设置的顺序。只有当 reading-flow
属性不为 normal
时,此属性才会对有效的阅读流程容器生效。
.wrapper {
display: block;
reading-flow: source-order;
}
.top {
reading-order: -1;
inset-inline-start: 50px;
inset-block-start: 50px;
}
以下块容器包含五项内容。没有任何布局规则会按其来源顺序重新排列元素,但有一个非流式项应先访问。
<div class="wrapper">
<a href="#">Item 1</a>
<a href="#">Item 2</a>
<a href="#">Item 3</a>
<a href="#">Item 4</a>
<a class="top" href="#">Item 5</a>
</div>
通过将此项的 reading-order
设置为 -1
,焦点顺序会先访问它,然后再回退到阅读流程其余项的来源顺序。
您可以在 chrome.dev 网站上找到更多示例。
与 tabindex 交互
过去,开发者使用 HTML tabindex
全局属性使 HTML 元素可聚焦,并确定顺序焦点导航的相对顺序。不过,此属性存在许多缺点和无障碍问题。主要问题是,无障碍树无法识别使用正 tabindex 创建的按 tabindex 顺序的焦点导航。如果使用不当,焦点顺序可能会跳跃,与屏幕阅读器上的体验不一致。要解决此问题,请使用 aria-owns HTML 属性跟踪排序。
在前面的 flex 示例中,若要获得与使用 reading-flow: flex-visual
相同的结果,您可以执行以下操作。
<div class="box" aria-owns="one three two">
<a href="#" tabindex="1" id="one">One</a>
<a href="#" tabindex="3" id="two">Two</a>
<a href="#" tabindex="2" id="three">Three</a>
</div>
但是,如果容器之外的其他元素也具有 tabindex=1
,会怎么样?
然后,系统会一起访问具有 tabindex=1
的所有元素,然后再移至下一个增量 tabindex 值。这种跳跃的顺序导航会导致用户体验不佳。因此,无障碍功能专家建议避免使用正 tabindex。在设计 reading-flow
时,我们尝试解决了这个问题。
设置了 reading-flow
属性的容器会成为焦点范围所有者。这意味着,它会将顺序焦点导航范围限定为访问容器内的每个元素,然后再移动到网页文档中的下一个可聚焦元素。此外,系统会使用 reading-flow 属性对其直接子项进行排序,并会忽略正 tabindex 以进行排序。您仍然可以在阅读流内容项的后代上设置正 tabindex。
请注意,具有 display: contents
且从其布局父项继承 reading-flow
属性的元素也将是一个有效的阅读流容器。在设计网站时,请注意这一点。如需详细了解,请参阅我们就 reading-flow
和 display: contents
征求反馈的请求。
请告诉我们
请试用本文中的示例以及 chrome.dev 上的 reading-flow
示例,并在您的网站上使用这些 CSS 属性。如果您有任何反馈,请在 CSS 工作组 GitHub 代码库中提交问题。如果您对 tabindex 和焦点范围行为有具体反馈,请在 HTML WHATNOT GitHub 代码库中提出问题。我们非常期待收到您对此功能的反馈。