reading-flow

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

实验性: 这是一项实验性技术
在生产中使用此技术之前,请仔细检查浏览器兼容性表格

reading-flow CSS 属性可以修改块级flexgrid 布局中子元素的阅读顺序。这会影响它们被朗读的顺序,以及在使用顺序导航(例如通过 Tab 键切换链接或按钮)时的导航顺序。

语法

css
/* Keyword values */
reading-flow: normal;
reading-flow: flex-visual;
reading-flow: flex-flow;
reading-flow: grid-columns;
reading-flow: grid-rows;
reading-flow: grid-order;
reading-flow: source-order;

/* Global values */
reading-flow: inherit;
reading-flow: initial;
reading-flow: revert;
reading-flow: revert-layer;
reading-flow: unset;

reading-flow 属性接受以下关键字之一作为其值。

normal

默认值。阅读顺序遵循 DOM 中元素的顺序。

flex-visual

仅影响flex 容器。阅读顺序遵循 flex 项的视觉顺序,同时会考虑 writing-mode。因此,对于一个英文文档,如果设置了 flex-direction: row-reversereading-flow: flex-visual,那么阅读顺序将是从左到右。

flex-flow

仅影响 flex 容器。阅读顺序遵循 flex-flow 的方向。

grid-columns

仅影响网格容器。阅读顺序遵循网格项的视觉顺序,逐列进行,同时会考虑书写模式。

grid-rows

仅影响网格容器。阅读顺序遵循网格项的视觉顺序,逐行进行,同时会考虑书写模式。

grid-order

仅影响网格容器。如果 order 属性被应用于容器的任何子元素,阅读顺序将遵循修改后的项目顺序。如果 order 属性未应用于网格项,则 grid-order 的行为与 normal 相同。

source-order

影响网格、flex 和块级容器。其本身没有效果——容器的阅读顺序仍然遵循 DOM 中元素的顺序——但它允许通过在容器的子元素上设置 reading-order 属性来修改阅读顺序。

描述

reading-flow 属性的值不为 normal 时,它会修改块级flexgrid 容器内元素的阅读顺序。这样的容器被称为阅读流容器

默认情况下,网页内容是按照 DOM 源顺序朗读的。通常,源顺序应该表达出内容合理的阅读顺序,并且这也应该反映在内容布局的视觉顺序上。然而,有时视觉顺序或 Tab 键顺序会与源顺序不同。例如,当通过媒体查询为文档应用多个 flexbox 或 grid 布局以适应不同的设备或用户需求时,内容顺序可能会根据视口宽度而有所不同。在这种情况下,可以使用 reading-flow 来确保阅读和 Tab 键切换的顺序能反映视觉顺序。

在某些情况下,你可能希望进一步微调阅读流容器内的阅读顺序。你可以在容器的子元素上使用 reading-order 属性值,将它们放入序数组中,然后按数字顺序朗读。

tabindex 的交互

如果一组阅读流容器的子元素通常不可聚焦,但通过 tabindex="0" 属性使其变得可聚焦,那么它们的阅读顺序会像 <a><button> 等交互式元素一样,被 reading-flowreading-order 属性按预期修改。

然而,任何试图使用正值的 tabindex 来修改阅读流容器内容的 Tab 键顺序的尝试都将被忽略——它会被 reading-flowreading-order 的效果所覆盖。通常,你无论如何都不应该使用这些;请参阅不要使用大于 0 的 Tabindex。如果需要,reading-flowreading-order 属性提供了一种更好的方式来修改 Tab 键顺序。

正式定义

在数据库中未找到值!

示例

Flex 值比较

在此示例中,我们演示了不同的 reading-flow 值对一个具有反向 flex 项的 flex 容器的影响。

HTML

标记包括一个用于选择不同 reading-flow 值的 <select> 元素,以及一个包含三个 <a> 元素的包装器 <div>

html
<form>
  <label for="reading-flow">Choose reading flow:</label>
  <select id="reading-flow">
    <option>normal</option>
    <option>flex-visual</option>
    <option>flex-flow</option>
  </select>
</form>
<div class="wrapper">
  <a href="#">Item 1</a>
  <a href="#">Item 2</a>
  <a href="#">Item 3</a>
</div>

CSS

我们使用 display 值为 flex<div> 变为 flex 容器,并使用 flex-direction 值为 row-reverse 以反向 DOM 顺序将 flex 项显示为一行。最初,我们设置 reading-flownormal,因此项目会按 DOM 源顺序被朗读或通过 Tab 键切换。

我们还为第一个 <a> 元素设置了 order 值为 1,使其在 flex 流中显示在第二个和第三个项目之后。最终 flex 项从左到右的视觉顺序是“Item 1”、“Item 3”,然后是“Item 2”,但 DOM 顺序保持不变。

css
.wrapper {
  display: flex;
  flex-direction: row-reverse;
  reading-flow: normal;
  gap: 1em;
}

a:first-child {
  order: 1;
}

JavaScript

在我们的脚本中,我们获取了对 <select> 元素和包装器 <div> 的引用,然后为 <select> 元素添加了一个 change 事件监听器。当选择一个新值时,它将被设置为包装器的 reading-flow 属性值。

js
const selectElem = document.getElementById("reading-flow");
const wrapperElem = document.querySelector(".wrapper");

selectElem.addEventListener("change", () => {
  wrapperElem.style.readingFlow = selectElem.value;
});

结果

该示例渲染效果如下:

首先,在 reading-flow: normal 的设置下,尝试通过 Tab 键遍历链接。Tab 键顺序是“Item 1”、“Item 2”,然后是“Item 3”,因为这是元素在 DOM 中的顺序。

现在尝试更改 reading-flow 值,然后再次通过 Tab 键遍历链接。

  • 值为 flex-visual 时,项目将按“Item 1”、“Item 3”,然后是“Item 2”的顺序通过 Tab 键切换,这是应用 flexbox 属性后产生的视觉显示顺序。
  • 值为 flex-flow 时,项目将按“Item 2”、“Item 3”,然后是“Item 1”的顺序通过 Tab 键切换,这与 flex-flow 的方向相匹配——在本例中是 row-reverse。这里,Tab 键顺序与显示顺序相反。

Grid 值比较

在此示例中,我们演示了不同的 reading-flow 值对网格容器的影响。

HTML

标记包括一个用于选择不同 reading-flow 值的 <select> 元素,以及一个包含四个 <a> 元素的包装器 <div>

html
<form>
  <label for="reading-flow">Choose reading flow:</label>
  <select id="reading-flow">
    <option>normal</option>
    <option>grid-rows</option>
    <option>grid-columns</option>
    <option>grid-order</option>
  </select>
</form>
<div class="wrapper">
  <a class="a" href="#">Item A</a>
  <a class="b" href="#">Item B</a>
  <a class="c" href="#">Item C</a>
  <a class="d" href="#">Item D</a>
</div>

CSS

我们使用 display 值为 grid<div> 变为网格容器,并使用 grid-template-columns 将网格项显示为三列。我们还设置了 grid-template-areas 来描述这些列中的不同放置区域,并使用 grid-area<a> 元素放置在这些区域中。最初,我们设置 reading-flownormal,因此项目会按默认的 DOM 源顺序被朗读或通过 Tab 键切换。

最后,我们为第一个 <a> 元素设置了 order 值为 1;这对布局没有影响,因为它不会覆盖网格区域的放置,但当设置了某个 reading-flow 值时,它会产生效果,你稍后会看到。

从左到右阅读,网格项最终的显示顺序是“Item D”、“Item B”、“Item C”,然后是“Item A”。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 150px);
  grid-template-areas:
    "d b b"
    "c c a";
  reading-flow: normal;
}

.a {
  grid-area: a;
}
.b {
  grid-area: b;
}
.c {
  grid-area: c;
}
.d {
  grid-area: d;
}

a:first-child {
  order: 1;
}

JavaScript

在我们的脚本中,我们获取了对 <select> 元素和包装器 <div> 的引用,然后为 <select> 元素添加了一个 change 事件监听器。当选择一个新值时,它将被设置为包装器的 reading-flow 属性值。

js
const selectElem = document.getElementById("reading-flow");
const wrapperElem = document.querySelector(".wrapper");

selectElem.addEventListener("change", () => {
  wrapperElem.style.readingFlow = selectElem.value;
});

结果

该示例渲染效果如下:

首先,在 reading-flow: normal 的设置下,尝试通过 Tab 键遍历链接。Tab 键顺序是“Item A”、“Item B”、“Item C”和“Item D”,因为这是元素在 DOM 中的顺序。

现在更改 reading-flow 值,然后再次尝试通过 Tab 键遍历链接。

  • 值为 grid-rows 时,项目将按视觉显示顺序逐行通过 Tab 键切换。顺序是“Item D”、“Item B”、“Item C”,然后是“Item A”。
  • 值为 grid-columns 时,项目将按视觉显示顺序逐列通过 Tab 键切换。顺序是“Item D”、“Item C”、“Item B”,然后是“Item A”。
  • 值为 grid-order 时,项目将按 DOM 顺序通过 Tab 键切换,但会考虑任何 order 值的更改。由于我们对第一个 <a> 元素设置了 order: 1;,因此 Tab 键顺序是“Item B”、“Item C”、“Item D”,然后是“Item A”。

块级容器上的阅读顺序调整

在此示例中,我们演示了 reading-flow: source-order 值对块级容器的影响。

HTML

标记包括一个包装器 <div>,其中包含四个 <a> 元素。

html
<div class="wrapper">
  <a class="a" href="#">Item A</a>
  <a class="b" href="#">Item B</a>
  <a class="c" href="#">Item C</a>
  <a class="d" href="#">Item D</a>
</div>

CSS

我们设置 reading-flowsource-order,因此项目会按 DOM 源顺序被朗读或通过 Tab 键切换,但允许通过 reading-order 修改阅读顺序。我们为第一个 <a> 元素设置了 reading-order 值为 1

css
.wrapper {
  reading-flow: source-order;
}

a:first-child {
  reading-order: 1;
}

结果

该示例渲染效果如下:

尝试通过 Tab 键遍历链接:Tab 键顺序是“Item B”、“Item C”、“Item D”,然后是“Item A”——遵循了元素在 DOM 中的顺序,但 Item A 被置于比其他项更高的阅读顺序序数组中(默认的 reading-order 值为 0),因此它最后被切换到。

规范

规范
CSS Display Module Level 4
# reading-flow

浏览器兼容性

另见