网格布局和可访问性

那些从事网络开发多年的人可能会认为 CSS 网格有点像使用“表格进行布局”。在网络设计早期,我们构建页面布局的方式是使用 HTML 表格,然后将我们的设计片段化为这些表格的单元格,以创建布局。这种方式比随后的“CSS 定位”有一些优势,因为我们可以利用表格显示提供的对齐和全高列。然而,最大的缺点是它将我们的设计绑定到标记,通常在这样做时会产生可访问性问题。为了在表格中布局设计,我们经常以屏幕阅读器读取时毫无意义的方式拆分内容,例如。

在转向 CSS 时,我们经常谈论 CSS 用于布局,它可以实现内容、标记和表现形式的分离。最终目标是,我们可以创建一个语义化且结构良好的文档,然后应用 CSS 来创建我们想要的设计。像 CSS Zen Garden 这样的网站展示了这种能力。CSS Zen Garden 挑战我们使用相同的标记,使用 CSS 创建独特的设计。

CSS 网格布局 没有像表格那样存在问题,我们的网格结构是在 CSS 中定义的,而不是在标记中定义的。如果我们需要添加一个元素,我们可以使用一个没有语义意义的东西。在纸面上,网格帮助我们真正实现内容与标记分离的承诺,但是我们有可能过度使用这个想法吗?我们有可能通过使用网格创建可访问性问题吗?

在 CSS 网格布局中重新排序内容

我们已经在这份指南中看到,网格赋予我们重新排列页面内容的强大能力。我们可以使用 order 属性,它将改变项目的自动放置方式。我们可以使用 grid-auto-flow: dense,它将从视觉上将项目从 DOM 顺序中移除。我们还可以使用基于行的网格模板区域放置项目,而无需考虑它们在源代码中的位置。

规范 包含一个涵盖重新排序和可访问性的部分。在该部分的介绍中,详细介绍了规范期望浏览器在使用网格布局对内容进行视觉重新排序时执行的操作。

网格布局赋予作者对文档进行重新排列的强大能力。但是,这些能力不能替代对文档源代码的正确排序。order 属性和网格放置不会影响非视觉媒体(如语音)中的排序。同样,视觉上重新排列网格项目不会影响顺序导航模式(如循环遍历链接,例如参见 tabindex HTML5)的默认遍历顺序。

如果您使用网格布局在视觉上重新排序项目,这不会改变屏幕阅读器或其他文本转语音用户代理读取内容时的项目排序方式。此外,重新排序不会改变标签顺序。这意味着,使用键盘导航的人可能会在您的网站上按 Tab 键浏览链接,然后突然发现自己从文档顶部跳转到底部,因为重新排序的项目是下一个要显示的项目。

规范警告作者(CSSWG 对 Web 开发人员的称呼)不要进行此类重新排序。

作者必须仅使用 order 和网格放置属性来进行视觉上而不是逻辑上的内容重新排序。使用这些功能进行逻辑重新排序的样式表是非标准的。

这对实际使用网格布局进行设计意味着什么?

视觉上而不是逻辑上的重新排序

无论何时使用网格布局或 Flexbox 对项目进行重新排序,您只执行 *视觉重新排序*。底层的源代码控制着文本转语音以及文档的标签顺序。您可以通过一个非常简单的示例来了解其工作原理。

在此示例中,我使用网格布局了一组包含链接的方框。我使用了基于行的放置属性将方框 1 放在网格的第二行。从视觉上看,它现在显示为列表中的第四个项目。但是,如果我从一个链接切换到另一个链接,标签顺序仍然从方框 1 开始,因为它在源代码中排在第一位。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
}

.box1 {
  grid-column: 1;
  grid-row: 2;
}
html
<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 在逻辑上确实属于该位置,我们应该回到源代码中进行更改,而不是使用网格布局进行重新排序。这就是视觉重新排序与逻辑重新排序的区别,逻辑排序对于文档的含义和结构至关重要,我们应该确保保留这种结构。

我们应该如何处理网格布局的可访问性?

从规范中我们知道,我们需要确保我们的文档保持内容的逻辑顺序。我们应该如何进行开发,才能确保我们为不同的用户以及他们与网页交互的方式保持可访问性?

从结构化且可访问的文档开始

网格布局意味着我们不需要更改文档源代码就能获得我们想要的布局。因此,页面的起点应该是结构良好且可访问的源文档。正如 CSS 网格布局规范中所指出的,这往往会为您 *最小的屏幕设备* 提供良好的结构。如果用户在移动设备上滚动浏览一个很长的文档,该用户的优先级通常与源代码中的优先级一致。

创建响应式且负责任的网格

有了可靠的文档,您就可以开始添加布局了,您可能会使用 媒体查询 来创建额外的列并为不同的屏幕尺寸和设备进行更改。网格布局在这一点上非常有用,例如,在移动设备源代码顺序中优先级较低的元素可以移动到桌面布局的侧边栏中。关键是不断测试,一个非常简单的测试是 *在文档中按 Tab 键*。这种顺序是否仍然合理?检查一下您是否不会以奇怪的方式从布局的顶部跳到底部。如果是这样,那就意味着您需要解决布局中的某些问题。

返回到源代码

如果您在设计过程中的任何时候发现自己使用网格布局重新定位元素的位置,请考虑是否应该返回到您的文档并对逻辑顺序进行更改。使用 CSS 网格布局的好处是,您应该能够在源代码中移动一个项目以匹配逻辑顺序,而无需对布局进行大的更改。与基于 float 的布局相比,这是一个巨大的进步,在基于 float 的布局中,文档源代码对于获得不同断点处的布局非常重要。但是,作为开发人员,我们有责任记住返回到源代码并对其进行更新以维护逻辑顺序。

网格和标记扁平化的危险

在 CSS 网格布局和 CSS Flexbox 中,另一个需要注意的问题是,人们会不自觉地想要 *扁平化* 标记。正如我们所发现的,要使一个项目成为网格项目,它需要是网格容器的直接子元素。因此,如果您在网格容器内有一个 <ul> 元素,那么 *该* ul 元素将成为网格项目——子 <li> 元素不会。

grid-template-columnsgrid-template-rowssubgrid 值将在广泛实施后解决这个问题。它将允许网格被网格项目继承并向下传递。

鉴于 subgrid 的互操作性支持有限,在使用 CSS 网格布局开发网站时,人们确实会不自觉地想要扁平化标记,即删除语义元素,以简化布局的创建。例如,如果某些内容在语义上被标记为列表,但您决定使用一组 <div> 元素,那么您就可以让元素成为设置为 display: grid 的容器的直接子元素。请注意这种不自觉的倾向,并找到无需剥离标记就能开发设计的方法。从结构良好的文档开始是一个很好的方法,可以避免这个问题,因为如果您需要进入文档并进行删除,您会意识到自己在删除语义元素是为了让布局正常工作!

进一步阅读

关于可访问性和 CSS 网格布局的现有资料并不多。许多问题与针对 CSS Flexbox 提出的问题类似,CSS Flexbox 也提供了使用 flex-directionorder 属性对内容进行重新排序的方法。

视觉显示遵循文档源代码顺序的概念在 *WCAG 成功标准技术——技术 C27* 中有详细说明。

为了开始思考这些问题,当您使用 CSS 网格布局时,我建议阅读 Léonie Watson 撰写的 *Flexbox 与键盘导航断开连接*。此外,Léonie 在 ffconf 上的演讲视频 有助于更多地了解屏幕阅读器如何处理 CSS 中视觉元素的表示。Adrian Roselli 也在关于 不同浏览器中的标签顺序 发表了文章——尽管这篇文章是在 Firefox 尚未完全实施网格支持之前。