网格布局和无障碍性
HTML 是网站的内容层,我们用它来创建语义化、结构良好的文档。CSS 是表示层;我们应用 CSS 来为我们的内容创建所需的布局等。二维网格结构是使用 CSS 网格布局定义的。
尽管现代的 HTML 和 CSS 旨在创建语义化、可访问的内容和设计,但有些方法仍可能用网格造成可访问性问题。本文将探讨可能出现的潜在问题,以及如何避免它们。
在 CSS 网格布局中重新排序内容
我们已在这些指南中看到,CSS 网格布局赋予了我们通过使用基于线的网格模板区域放置来重新排序页面内容的能力。这种放置可以不考虑项目在源中的位置。此外,还有 order 属性,它可以改变项目的自动放置方式。grid-auto-flow 属性有一个 dense 值,这可能会使项目在视觉上脱离 DOM 顺序。
CSS 网格布局规范包含一个“重新排序和可访问性”部分。该部分的引言详细说明了当内容使用网格布局进行视觉重排时,浏览器应该如何处理:
网格布局赋予了作者对文档进行重新排列的强大能力。然而,这些能力不能替代正确的文档源顺序。
order属性和网格放置不影响非视觉媒体(如语音)中的顺序。同样,视觉上重新排列网格项目也不影响顺序导航模式(如循环切换链接,参见tabindex)的默认遍历顺序。
如果你使用网格布局在视觉上重新排序,这不会改变内容被屏幕阅读器或其他文本转语音用户代理朗读时的项目顺序。此外,重新排序也不会改变 Tab 键的顺序。这意味着使用键盘导航的人可能会在网站的链接间按 Tab 键切换,然后突然发现自己从文档顶部跳转到底部,因为一个被重新排序的项目在 Tab 键顺序中是下一个。
规范警告作者(CSSWG 对 Web 开发者的术语)不要进行这种重新排序。
作者必须只将
order和网格放置属性用于视觉上的,而非逻辑上的内容重排。使用这些特性进行逻辑重排的样式表是不符合规范的。
这在实践中对于使用网格布局进行设计意味着什么呢?
视觉重排而非逻辑重排
任何时候你使用网格布局——或 flexbox——重新排序时,你只进行了视觉重排。底层的源代码控制着诸如文本转语音和文档的 Tab 键顺序等。我们可以通过一个例子来看看这是如何工作的。
在这个例子中,我们有一个包含五个项目的网格,每个项目都包含一个链接。这些项目通过基于线的放置属性进行定位。我们将方框 1 放置在网格的第二行,因此它在视觉上显示为列表中的第四个项目。如果我们用 Tab 键在链接间导航,Tab 键的顺序仍然从方框 1 开始,因为它在源代码中是第一个。
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
}
.box1 {
grid-column: 1;
grid-row: 2;
}
<div class="wrapper">
<div class="box box1"><a href="">One</a></div>
<div class="box box2"><a href="">Two</a></div>
<div class="box box3"><a href="">Three</a></div>
<div class="box box4"><a href="">Four</a></div>
<div class="box box5"><a href="">Five</a></div>
</div>
规范指出,在这种情况下,如果方框 1 在那个位置上确实在逻辑上是合理的,我们应该回到我们的 HTML 源代码中进行更改,而不是使用网格布局重新排序。这就是视觉重排与逻辑重排的含义;逻辑顺序对我们文档的意义和结构很重要,我们应该确保我们保留这种结构。
我们应该如何处理网格布局的可访问性?
从规范中我们知道,需要确保我们的文档保持内容的逻辑顺序。我们应该如何进行开发,以确保为不同的用户以及他们与我们页面的交互方式保持可访问性呢?
- 从结构化和可访问的文档开始
-
一个好的网格布局应该意味着我们不需要为了得到想要的布局而改变我们的文档源代码。因此,你的页面的起点应该是一个结构良好且可访问的源文档。这通常也能为你的最小屏幕设备提供一个良好的结构。当用户在移动设备上滚动浏览长文档时,该用户的优先级通常与源代码中的优先级相对应。
- 创建一个响应式且负责任的网格
-
在 HTML 中定义了坚实的文档结构后,你可以使用 CSS 在其上添加布局。你很可能会使用 媒体查询 来为不同的屏幕尺寸和设备进行更改,包括为更大的屏幕创建额外的列。网格在这里非常有用。例如,在移动端源代码中优先级较低的元素可以在桌面布局中被移动到侧边栏。这里的关键是持续测试。一个好的测试方法是在文档中按 Tab 键切换。顺序是否仍然合理?检查你是否会以一种奇怪的方式从布局的顶部跳到底部。这是一个迹象,表明你需要解决布局中的某些问题。
- 回归源代码
-
如果在设计过程中的任何时候,你发现自己正在使用网格来重新定位一个元素,请考虑是否也应该回到你的文档中并对逻辑顺序进行更改。使用 CSS 网格布局的好处在于,你应该能够在源代码中移动一个项目以匹配逻辑顺序,而无需对你的布局进行大的更改。我们作为开发者有责任记住要回到源代码中更新它以保持逻辑顺序。
网格和标记扁平化的危险
在 CSS 网格布局中,以及在某种程度上在 CSS flexbox 中,另一个需要注意的问题是扁平化标记的诱惑。正如我们所发现的,一个项目要成为网格项目,它需要是网格容器的直接子元素。因此,当你在网格容器内有一个 <ul> 元素时,那个 ul 成为一个网格项目——其子元素 <li> 则不会。
grid-template-columns 和 grid-template-rows 的 subgrid 值解决了这个问题。它允许网格被网格项目继承并向下传递到树中。或者,在网格项目上设置 display: contents 会使其子元素成为网格项目。如果你将一个项目设置为 display: contents,它通常会创建的盒子会消失,而子元素的盒子会看起来像是提升了一个层级。
从一个结构良好的文档开始,是避免可访问性问题的一个非常好的方法。
另见
- Flexbox 与键盘导航的脱节 和 (终究是人):可访问性混音视频 via Léonie Watson (2016)
- 网格、内容重排和可访问性 via CSS-tricks (2019)
display: contents不是 CSS 重置 via Adrian Roselli (2024)