{T}

可访问性

启程,共同迈进一个更加平等、包容的数字世界。

SVG 可访问性概述

SVG 是一种在 Web 开发中常用的矢量图形格式,它具有无限放大不失真的优势,因此被广泛用于创建图标、图形和其他视觉元素。尤其是,随着 JavaScript 的发展和 CSS 媒体查询(例如 @prefers-color-scheme@prefers-reduced-motion)的引入,SVG 的功能已远远超出了最初仅用在 Web 上显示矢量图像的用例。

随着 SVG 技术的进步,我们对如何设计和开发 SVG 的理解也需要相应提升。其中一部分进步就包括考虑这些设计和代码对用户的平等性和包容性。换句话说,需要让确保 SVG 图形对于所有用户都可以访问,特别是对于那些使用辅助技术的用户,如屏幕阅读器的用户。然而,要做到这一点并不容易。

为什么 SVG 可访问性很重要?

在 Web 的无障碍设计中,可访问性是至关重要的。SVG 可访问性的重要性体现在以下几个方面:

  • 包容性:Web 应该为所有人提供平等的访问机会,无论他们的能力水平如何。通过确保 SVG 图形对于视觉受限的用户同样可访问,可以促进数字包容性。
  • 合规性:随着无障碍法规和标准的不断发展,对于网站和应用程序的可访问性要求也在不断提高。确保 SVG 可访问性是符合法规和标准的一项重要举措。
  • 用户体验:为用户提供友好的体验是每个 Web 开发者的责任。通过优化 SVG 图形的可访问性,可以提高用户的满意度和舒适度。

SVG 可访问性要素

SVG 不仅仅是一门技术,它是连接创意与包容的桥梁。保障 SVG 可访问性的目的在于使得图形内容对于诸如视觉受限的用户同样可访问,确保所有用户都能够获得平等的信息获取和使用体验。

具体来说,SVG 可访问性包括以下几个方面:

  • 语义标记:使用适当的语义标记来描述 SVG 图形的内容和意义,使其对于屏幕阅读器和其他辅助技术能够准确解释。这意味着在 SVG 中使用元素和属性来明确表示图形的含义和结构。同时确保这些元素具有适当的 ARIA 属性来定义其角色和状态。
  • 标题和描述:为 SVG 图形添加标题和描述,以提供关于图形内容和用途的额外信息。这对于视觉受限的用户特别重要,因为他们可能无法直接看到图形。标题通常使用 <title> 元素,而描述则使用 <desc> 元素。
  • 焦点管理:确保 SVG 图形能够正确地接受焦点,并在键盘导航时可以被访问。这包括确保图形在页面上的正确定位和焦点顺序,以及在图形被点击时能够执行相应的操作。
  • 色彩对比度:考虑图形中的颜色对比度,以确保视觉上的清晰度和可读性,尤其是对于色盲用户。使用高对比度的颜色组合可以提高图形的可访问性,并使其更易于理解和辨认。
  • 交互性:使 SVG 中的交互元素(如按钮、链接)可以通过键盘导航,并确保它们响应合适的键盘事件和触控事件,同时提供视觉、听觉或触觉反馈。
  • 动画与时间控制:对于含有动画的 SVG,确保动画可以被用户控制(如暂停、播放、调整速度),并为动画内容提供描述,以便那些无法看到动画的用户理解动态变化。
  • 避免冗余 ID 和重复标签:确保 SVG 代码中没有重复的 ID,因为这可能导致可访问性问题和验证错误。同时,正确地标记和描述所有的图形元素,避免信息混乱。

通过综合考虑这些方面,并采取相应的措施来优化 SVG 图形的可访问性,可以确保这些图形在 Web 环境中能够对所有用户都是友好和可访问的。

接下来,将探索一些普遍存在的 SVG 模式的可访问性设置,以及如何使你的 SVG 更具可访问性的一些实际案例。

SVG 可访问性设置模式

通过前面的学习,我们知道 SVG 应用于 Web 网站或应用程序有多种不同的方式,最为常见的是:

  • SVG 作为图像文件被 <img> 元素引入到 Web 中;
  • SVG 代码直接嵌套在 HTML 文档中。

SVG 不同的使用方式,在可访问性方面设置也是有所差异的。

使用 <img> 标签引入 SVG

HTML 的 <img> 标签元素对于任何一位 Web 开发者来说都不会感到陌生。时至今日,它依旧是给 Web 网站或应用引入图片的最简单、最直接的方式。而 SVG 文件也是众多图像格式中的一种,这也意味着,使用 <img> 可以直接引用一个 SVG 文件,并将其在 Web 中呈现。例如:

HTML
<img src="a11y.svg" alt="A11y" />

正如上面代码所示,非常简单,简单到无需做任何的解释。

虽然 <img> 元素给 Web 网站或应用引入图片的方式简单直接,但引入的图片用于何处、在 Web 上起何作用,是有所区别的。因此,为了让所有用户(包括那些依赖辅助技术的用户)能更好地理解引入图片的功能,我们在使用 <img> 元素时,有一些细节是需要知道的,尤其是可访问性方面。

简单地说,Web 上的图像分为“传达信息的图像”和“装饰性的图像”。

  • 传达信息的图像指的是通过视觉元素来传递特定信息或概念的图像。这些图像可能包括图表、图标、图形、表格、地图等形式,它们通过视觉方式向观众传达信息,而不需要依赖文字。这些图像的设计目的是清晰地传达特定的概念、数据或想法,从而帮助观众更好地理解和记忆信息。

  • 装饰性的图像是指在视觉上具有美学或装饰作用,而不是用于传达特定信息或概念的图像。这些图像通常用于美化设计、增强视觉吸引力或提供情感上的附加价值。与传达信息的图像不同,装饰性的图像并不需要观众理解特定的含义或概念,而是旨在激发情感或提供视觉享受。

也就是说,如果 <img> 元素引入的是一个用于传达有用信息的图像,那么就需要通过一些技术手段来向特殊用户传达。通常情况下,使用 <img> 元素的 alt 属性是传达图像有用信息的最佳方式:

HTML
<img src="a11y.png" alt="图像需要传达的信息" />

虽然 titlearia-labelaria-labelledby 属性也可以为图像元素提供可访问名称,但只有 alt 会在图像损坏或被阻止时始终呈现回退文本。

如果 <img> 元素引入的是一张“装饰性的图像”,那么需要将 <img> 元素的 alt 设置为空,因为这样做可以被屏幕阅读器忽略,以帮助减少不必要或多余的信息:

HTML
<img src="example.jpg" alt="" />
<!-- 或者 -->
<img src="example.jpg" alt>

注意,使用 <img> 引入的图片有的时候会和一些可交互元素结合使用,例如链接(<a>)和按钮(<button>)等。在此情况之下,即使引入的是一张传达信息的图片,在使用的时候也要根据具体情景做出相应的调整。

例如:

HTML
<!-- 请不要这样做 -->
<a href="#">
    <img src="search.png" alt="Search" />
    Search
</a>

<button>
    <img src="search.png" alt="Search" />
    Search
</button>

上面这样做,对于一些辅助技术,如屏幕阅读器是非常不友好的,它会读出重复性的内容,即会重复读出“Search”两次,然后可能会伴随读出元素的角色,例如“图像”、链接和按钮等。这个情景之下,<img> 元素的 alt 为空将使其被视为装饰性内容更为妥当:

HTML
<a href="#">
    <img src="search.png" alt="" />
    Search
</a>

<button>
    <img src="search.png" alt="" />
    Search
</button>

在只有图形单独表示链接或按钮的情况下,没有必要添加可视隐藏文本,或者使用 ARIA 属性提供链接或按钮的可访问名称。以下标记模式将为链接或按钮提供可访问名称“search”:

HTML
<a href="#">
    <img src="search.png" alt="Search" />
</a>

<button>
    <img src="search.png" alt="Search" />
</button>

同样的,SVG 也有分“传达信息的 SVG”和“装饰性的 SVG”。当一个具有信息的 SVG 文件被 <img> 元素引入到 Web 中时,请不要忘记给 <img>alt 属性设置内容:

HTML
<img src="search.svg" alt="Search" />

除此之外,还有一些其他的模式:

HTML
<!-- 模式 ① -->
<img src="search.svg" alt="Search" />

<!-- 模式 ② -->
<img src="search.svg" role="img" alt="Search" />

<!-- 模式 ③ -->
<img src="search.svg" role="img" aria-label="Search" alt="" />

<!-- 模式 ④ -->
<img src="search.svg" role="img" aria-labelledby="search" alt="" />
<div id="search" class="sr-only"/>Search</div>
<p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/29bc8d3ab5c343dc96cfe8ee24567f16~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=2000&h=1809&s=713421&e=jpg&b=7d850c" alt="" /></p>

注意,示例中的 rolearia-labelaria-labelledby 是 ARIA 方面的知识,你可以通过 ARIA In HTMLWAI-ARIA 规范中获得更详细的介绍。这里假设你对这些属性有一定的了解!

事实上,当 SVG 被 <img> 引入 Web 时,它与其他格式图像的使用并无差异,甚至可以说,它与 SVG 没有太大的关系。我们只需要掌握 <img> 元素可访问性方面的知识即可。这对于熟悉 Web 可访问性知识的开发者来说,并不是难事。

额外提一下,<img>alt 属性的描述对于图片是否更具可访问性,很关键。可以按照下面这些原则来进行:

  • 尽可能具体地描述图像alt 首先是为那些无法看到图像的用户提供文本解释。如果一个图像真的没有传达任何意义或价值,只是为了设计而存在,那么它应该存在于 CSS 中(背景图像),而不是 HTML 中。
  • 保持简短alt 中的内容对于屏幕阅读器来说是友好的,但并不是说任意字符串都是友好的。最受屏幕阅读器欢迎的alt的文本长度应该限制在 125 个字符左右,因此建议将其限制在该字符数以内。
  • 使用关键字:在 alt 中尽可能使用关键字来描述,这样除了可以描述图像信息之外,还可以在页面中提供关键字的另一个机会。如果从搜索引擎的角度来说,多给了搜索引擎发出有用号,表明你的页面与特定的搜索查询更匹配,更利于被搜索引擎搜索到。虽然 alt 中的文本首要任务是用来描述图像和为图像提供上下文信息,但是这样做是有意义的,即在页面上至少一个图像的 alt 文本中包含你的关键字
  • 避免关键字堆砌:虽然关键词对于搜索引擎是有用的(可以发送更有用的信号),但也不能将很多个关键字都往 alt 中堆。这样做,像 Google 这样的搜索引擎虽不会扣分,但这样做反而是画蛇添足。因为alt的重点(目的)是用来描述图像的(试想一下,在alt中添加了很多和图像不匹配的关键字,对于依赖于辅助技术的用户而言,反而会令他们更无法理解图像的信息)。
  • 不要在 alt 文本中包含 “Image of”、"Picture of"、"Graphic of" 和 “图像” 等alt<img> 标签元素的属性,实际上已经指向一个图像,所以没必要指定它。
  • 不要忘记 longdes 属性alt 对于屏幕阅读器最佳的字符数是125个字符,但很多时候你希望用更详细的文本向用户描述图像,那么这个时候应该使用 longdes 这个属性。
  • alt 属性可以是空值,但 <img> 不能没有该属性:所有图像都应该有一个 alt 标签,但可以是空值(即空字符串),当图像不想表达任何的信息或上下文时(比如一些用于设计元素的图像),那么可以让alt属性的值为空。这样做可以让屏幕阅读器跳过该图像。注意:使用空值的 alt 和不使用 alt 是有本质区别的

SVG 内嵌在 HTML 中

SVG 应用于 Web 另一种常见方式是直接将 SVG 代码嵌套在 HTML 中:

HTML
<svg viewBox="0 0 512 512">
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

通过将 SVG 直接嵌套到 HTML 中,你可以为屏幕阅读器用户提供图像信息时有更多的选择。

这是因为,SVG 与光栅图像不同,SVG 可以有诸如 <title><desc> 等元素,这些元素可以用于向辅助技术提供信息。例如:

HTML
<!-- 模式 ① -->
<svg role="img">
    <title>Search</title>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

<!-- 模式 ② -->
<svg role="img">
    <text class="sr-only" font-size="0">Search</text>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

<!-- 模式 ③ -->
<svg role="img" aria-describedby="search">
    <title id="search">Search</title>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

<!-- 模式 ④ -->
<svg role="img" aria-labelledby="search">
    <title id="search">Search</title>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>
<p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2601bcaa438e4fa98a87a1ef061c59cc~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=2000&h=1809&s=699567&e=jpg&b=7d850c" alt="" /></p>

对于复杂的图像,我们还可以根据需要向 SVG 添加其他的信息。例如:

HTML
<!-- 模式 ① -->
<svg role="img">
    <title>Search</title>
    <text class="sr-only" font-size="0">Search for image</text>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

<!-- 模式 ② -->
<svg role="img">
    <title>Search</title>
    <desc>Search for image</desc>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

<!-- 模式 ③ -->
<svg role="img" aria-labelledby="search--title search--desc">
    <title id="search--title">Search</title>
    <desc id="search--desc">Search for image</desc>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

<!-- 模式 ④ -->
<svg role="img" aria-describedby="search--title search--desc">
    <title id="search--title">Search</title>
    <desc id="search--desc">Search for image</desc>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>
<p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ff317f5ed3c248e4a76ac37ba1557cb4~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=2000&h=1809&s=714050&e=jpg&b=7d850c" alt="" /></p>

综合下来,共有 12 种不同的使用模式,具体如下图所示:

<p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ff8536e837b94ffc9a884a87fd7d4666~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=3000&h=3436&s=2979604&e=jpg&b=7d850c" alt="" /></p>

注意,上图中 “💩”标识符表示不推荐使用的方式,“👍”标识符表示推荐使用的方式,未标任何标识符表示需谨慎使用!

<img> 引入 SVG 文件一样,嵌套在 HTML 中的 SVG 也分“传达信息的 SVG”和“装饰性的 SVG”。对于“传达信息的 SVG”,可以像下面这样使用:

HTML
<svg role="img" focusable="false">
    <title>Search</title>
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
</svg>

此模式下,屏幕阅读器能将 SVG 朗读为“图像”或“图形”,其可访问名称将被正确地朗读。

对于“装饰性的 SVG”,可以直接在 <svg> 元素上设置 aria-hidden="true" ,这样屏幕阅读器无法识别它,在这个过程中,最好也将 focusable 设置为 false

HTML
<svg aria-hidden="true" focusable="false">
    <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 ..." />
</svg>

由于 SVG 应该被隐藏,因此无需添加 role 属性,因为它会被忽略。

实战:具有可访问性的图标按钮

时下,很多 Web 应用都具有图标按钮或图标链接。从视觉上来看,它们有可能是纯图标,不带有任何文本描述;也有可能是图标加文本的方式存在:

<p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3163a1632996468ea7b60eb53f0dc1c4~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1170&h=2532&s=235979&e=jpg&b=fefdfd" alt="" width="70%"/></p>

正如上图所示,顶部四个图标按钮只包含了图标,但没有附带文本;其他的图标基本上都是附带了文本。

撇开用户体验的一面和图标本身是否足以向用户传达含义和功能,今天很多这样的图标按钮都缺乏对辅助技术的支持。这也意味着,依赖辅助技术(比如屏幕阅读器)的用户是很难理解图标按钮真正的含义与功能,使得他们无法正常访问和使用你的网站或应用。

正如前面所述,不管图标以哪种方式被引用到 Web 网站或应用,我们仅需要几个属性就可以使得它们变得更具可访问性,而且模式有很多种。

在具体介绍相应的解决方案之前,请大家试问一下自己,类似上图的应用场景,你是如何进行编码的。据我的了解,在移动端开发的场景中,大部分 Web 开发者喜欢使用不具任何语义化的标签来制作图标按钮,例如:

HTML
<div class="setting">
    <svg class="icon--setting" viewBox="0 0 512 512">
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</div>

<div class="home">
    <svg class="icon--home" viewBox="0 0 576 512">
        <path d="M543.8 287.6c17 0 32-14 32-32.1c1-9-3-17-11-24L512 185V64c0-17.7-14.3-32-32-32H448c-17.7 0-32 14.3-32 32v36.7L309.5 7c-6-5-14-7-21-7s-15 1-22 8L10 231.5c-7 7-10 15-10 24c0 18 14 32.1 32 32.1h32v69.7c-.1 .9-.1 1.8-.1 2.8V472c0 22.1 17.9 40 40 40h16c1.2 0 2.4-.1 3.6-.2c1.5 .1 3 .2 4.5 .2H160h24c22.1 0 40-17.9 40-40V448 384c0-17.7 14.3-32 32-32h64c17.7 0 32 14.3 32 32v64 24c0 22.1 17.9 40 40 40h24 32.5c1.4 0 2.8 0 4.2-.1c1.1 .1 2.2 .1 3.3 .1h16c22.1 0 40-17.9 40-40V455.8c.3-2.6 .5-5.3 .5-8.1l-.7-160.2h32z"/>
    </svg>
    首页
</div>

当然,也有部分开发者会使用 <a><button> 来替代上面代码中的 <div> 元素。

在进行 Web 开发的过程中,一直极力强调应该使用具有语义的 HTML 标签元素。比如上面的示例,假设你知道它是一个按钮,那就应该使用原生的 <button> 按钮:

HTML
<button class="setting">
    <svg class="icon--setting" viewBox="0 0 512 512">
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</button>

<button class="home">
    <svg class="icon--home" viewBox="0 0 576 512">
        <path d="M543.8 287.6c17 0 32-14 32-32.1c1-9-3-17-11-24L512 185V64c0-17.7-14.3-32-32-32H448c-17.7 0-32 14.3-32 32v36.7L309.5 7c-6-5-14-7-21-7s-15 1-22 8L10 231.5c-7 7-10 15-10 24c0 18 14 32.1 32 32.1h32v69.7c-.1 .9-.1 1.8-.1 2.8V472c0 22.1 17.9 40 40 40h16c1.2 0 2.4-.1 3.6-.2c1.5 .1 3 .2 4.5 .2H160h24c22.1 0 40-17.9 40-40V448 384c0-17.7 14.3-32 32-32h64c17.7 0 32 14.3 32 32v64 24c0 22.1 17.9 40 40 40h24 32.5c1.4 0 2.8 0 4.2-.1c1.1 .1 2.2 .1 3.3 .1h16c22.1 0 40-17.9 40-40V455.8c.3-2.6 .5-5.3 .5-8.1l-.7-160.2h32z"/>
    </svg>
    首页
</button>

不过,也有人推荐在不使用原生 <button> 按钮时,在元素上设置 role="button" ,使得屏幕阅读器也能将其识别为“按钮”。但我不建议这样使用。因为,无论哪种方式,当一个按钮被屏幕阅读器朗读(识别)为“按钮”时,用户会自然认为它是具有可交互的,比如鼠标点击或通过键盘的 Eenter 键或 Space 键激活按钮。

这也意味着,如果你选择的不是 <button> 元素,你将需要使用 JavaScript 去做很多额外的事情,比如实现按钮的交互行为和功能。但是,使用 <button> 元素,Web 开发者就无需考虑这些,只需要考虑如何让用户能更友好地访问他。

即便如此,要使屏幕阅读器能正确朗读出按钮的真实含义,还需做一些额外的事情,否则你写的按钮也是不具可访问性的,因为屏幕阅读器只能朗读出它是一个按钮,但不能告诉用户这个按钮的真正含义。例如上面代码中的两个按钮,第一个只会朗读出“按钮”,第二个则会朗读出“首页,按钮”。这是因为,前一个按钮没有任何可访问名称。

有一个小技巧,可以通过 Chrome 浏览器开发者工具来检查按钮的可访问名称。在样式标签旁边,你会找到一个“辅助功能”标签,在其中你将找到类似于下图这样的内容:

正如上图所示,按钮的可访问名称可以通过多种不同的方式定义。例如示例中第二个按钮,在按钮内放置了纯文本“首页”,该文本内容就可以用作按钮的可访问名称。这也是为什么第二个按钮获得焦点时,屏幕朗读器会朗读“首页,按钮”,而第一个则只会朗读“按钮”。

现在,你可以使用同样的方式检查一下自己项目中的按钮,看看它是否具备可访问名称,然后启动屏幕阅读器,看看它是如何被朗读的。

继续以前面两个按钮为例,你可能体会到了:

  • 第一个按钮,它里面仅包含了一个 SVG 图标,屏幕阅读器无法了解该按钮的真正含义。
  • 第二个按钮,它里面包含了一个 SVG 图标和文本,该文本将用于创建按钮的可访问名称。该文本向屏幕阅读器用户传达了按钮的功能(真正含义)。

就这个示例而言,对于第一个按钮(仅包含 SVG 图标),我们需要以某种方式为其提供可访问名称。比如,前面提到的内联 SVG 可访问性设置模式(稍后会介绍)。对于第二个按钮,可以做得更好一些。

因为,对于第二个按钮中的 SVG 图标,它对于屏幕阅读器用户一点意义都没有,因为它并不会给按钮添加可访问名称。因此,可以将 <svg> 元素的 aria-hidden 设置为 true ,使屏幕阅读器忽略它。

HTML
<button class="home">
    <svg aria-hidden="true" class="icon--home" viewBox="0 0 576 512">
        <path d="M543.8 287.6c17 0 32-14 32-32.1c1-9-3-17-11-24L512 185V64c0-17.7-14.3-32-32-32H448c-17.7 0-32 14.3-32 32v36.7L309.5 7c-6-5-14-7-21-7s-15 1-22 8L10 231.5c-7 7-10 15-10 24c0 18 14 32.1 32 32.1h32v69.7c-.1 .9-.1 1.8-.1 2.8V472c0 22.1 17.9 40 40 40h16c1.2 0 2.4-.1 3.6-.2c1.5 .1 3 .2 4.5 .2H160h24c22.1 0 40-17.9 40-40V448 384c0-17.7 14.3-32 32-32h64c17.7 0 32 14.3 32 32v64 24c0 22.1 17.9 40 40 40h24 32.5c1.4 0 2.8 0 4.2-.1c1.1 .1 2.2 .1 3.3 .1h16c22.1 0 40-17.9 40-40V455.8c.3-2.6 .5-5.3 .5-8.1l-.7-160.2h32z"/>
    </svg>
    首页
</button>

aria-hidden 属性用于指示元素是否向屏幕阅读器暴露。当设置为 true 时,该元素及其内容将从辅助功能 API 中隐藏,无论它是否被视觉显示。

我们还可以将 <svg>focusable 属性设置为 false ,这样可以避免 SVG 图标自身获得焦点,同时避免按钮具有两个 Tab 停止位。

HTML
<button class="home">
    <svg aria-hidden="true" focusable="false" class="icon--home" viewBox="0 0 576 512">
        <path d="M543.8 287.6c17 0 32-14 32-32.1c1-9-3-17-11-24L512 185V64c0-17.7-14.3-32-32-32H448c-17.7 0-32 14.3-32 32v36.7L309.5 7c-6-5-14-7-21-7s-15 1-22 8L10 231.5c-7 7-10 15-10 24c0 18 14 32.1 32 32.1h32v69.7c-.1 .9-.1 1.8-.1 2.8V472c0 22.1 17.9 40 40 40h16c1.2 0 2.4-.1 3.6-.2c1.5 .1 3 .2 4.5 .2H160h24c22.1 0 40-17.9 40-40V448 384c0-17.7 14.3-32 32-32h64c17.7 0 32 14.3 32 32v64 24c0 22.1 17.9 40 40 40h24 32.5c1.4 0 2.8 0 4.2-.1c1.1 .1 2.2 .1 3.3 .1h16c22.1 0 40-17.9 40-40V455.8c.3-2.6 .5-5.3 .5-8.1l-.7-160.2h32z"/>
    </svg>
    首页
</button>

请把注意力放到第一个按钮上来:

HTML
<button class="setting">
    <svg class="icon--setting" viewBox="0 0 512 512">
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</button>

正如前面所述,可以使用下图中的任一方式来使按钮具有可访问名称,使得屏幕阅读器用户能理解该按钮的含义或功能:

<p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b18352951a84b92a55c733568b7ddd0~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=3000&h=3436&s=2398460&e=jpg&b=7d850d" alt="" /></p>

模式一:<svg> + role="img" + <title>

首先推荐的模式是利用 <svg> 自己的 <title> 元素为按钮或链接提供可访问名称:

HTML
<button class="setting">
    <svg role="img" focusable="false" class="icon--setting" viewBox="0 0 512 512">
        <title>Setting</title>
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</button>

模式二:<svg> + role="img" + <title> + aria-labelledby="[ID]"

这种模式,aria-labelledby 将引用 SVG 的 <title> 元素作为可访问名。只不过,<title> 元素需要指定一个 id 标识符:

HTML
<button class="setting">
    <svg aria-labelledby="a11y-setting" role="img" focusable="false" class="icon--setting" viewBox="0 0 512 512">
        <title id="a11y-setting">Setting</title>
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</button>

模式三:<svg> + role="img" + <title> + <desc> + aria-labelledby="[ID]"

如果你希望对这个图标按钮做进一步的说明,比如告诉用户这个用于设置个人信息的“设置按钮”,那么还可以使用 SVG 的 <desc> 标签来对图片做更详细的描述,并通过 aria-labelledby 同时绑定 <title><desc> 元素的 id

HTML
<button class="setting">
    <svg aria-labelledby="a11y-setting a11y-setting-desc" role="img" focusable="false" class="icon--setting" viewBox="0 0 512 512">
        <title id="a11y-setting">Setting</title>
        <desc id="a11y-setting-desc">Setting personal information</desc>
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</button>

模式四:可访问的视觉隐藏文本

这种模式是一种较为传统的模式,将在按钮或链接内使用额外的标签,为按钮或链接添加文本,并使用 CSS 在视觉上将其隐藏,以便屏幕阅读器可以检测到并使用该文本。与此同时,会将 <svg> 元素的 aria-hidden 设置为 true ,这样屏幕阅读器将会忽略 SVG 图标:

HTML
<button class="setting">
    <svg aria-hidden="true" focusable="false" class="icon--setting" viewBox="0 0 512 512">
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
     <span class="sr-only">Setting</span>
</button>

注意,下面这段 CSS 很重要,它就是常称的视觉上隐藏文本的代码片段:

CSS
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}

这种模式还有一种简易方式可替代,那就是使用 hidden 属性来替代 .sr-only 类名来隐藏按钮文本。不过需要在 <span> 元素指定 id 名,并使用 aria-labelledby 来为其创建可访问名称:

HTML
<button class="setting" aria-labelledby="a11y-setting">
    <svg aria-hidden="true" focusable="false" class="icon--setting" viewBox="0 0 512 512">
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
     <span id="a11y-setting" hidden>Setting</span>
</button>

模式五:aria-label="[words]"

对于像按钮和链接这种可聚焦元素,我们还可以直接在该元素上使用 aria-label 为其提供可访问名称。如果按钮或链接上使用 aria-label 属性,那么该属性的内容将覆盖元素内部的内容作为可访问名称:

HTML
<button class="setting" aria-label="Setting">
    <svg aria-hidden="true" focusable="false" class="icon--setting" viewBox="0 0 512 512">
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</button>

上面的方式是在 <button> 上设置 aria-label 属性,其目的是避免使用 SVG 图标为按钮提供可访问名称。其实,我们并不一定要这样做。SVG 图标本身可以用来为按钮创建可访问名,其关键是要确保 SVG 图标本身具有可访问的标签。这一点,可以通过 role="img" 来做到。

也就是说,上面代码中设置在 <button>aria-label 属性,可以像下面这样直接设置在 <svg> 元素上:

HTML
<button class="setting">
    <svg role="img" aria-label="Setting" focusable="false" class="icon--setting" viewBox="0 0 512 512">
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
     </svg>
</button>

以上是为图标按钮提供可访问标签的几种方法。每种方法都有其优缺点,需要根据具体情况选择最合适的技术。就我个人而言,我不会使用 SVG 图标本身来为按钮提供标签,而是会直接在按钮上提供标签。这是因为,到目前为止,并没有一种良好的方法可以仅使用 SVG 来为按钮或链接提供可访问的名称。据 @Carie Fisher@Scott 提供的测试结果来看,仅 <svg> + role="img" + <title> + aria-labelledby="[ID]" 模式得到更多系统的支持。

如果你感兴趣的话,也可以打开你系统的“旁白”功能,访问下面这个案例中的按钮,亲身体验一下:

Demo 地址:https://codepen.io/airen/full/abrOOeV

上面所展示的单个 SVG 图标的应用。我们在进行 Web 开发的过程中,可能同一个 SVG 图标会在不同的位置和不同的页面出现。因此,很多时候会考虑应用 SVG Sprites(SVG 精灵)技术,使得 SVG 图标可以重复使用。通常情况使用 <symbol> 来创建图标实例,便于图标可以多次重复使用。

这种方法的最大优势是结果的能力,可以无限次重用图标并根据用例对其进行标记。不过,在使用 <symbol> 创建 SVG 雪碧图时,为了使图标更具可访问性,有人建议在使用 <symbol> 创建图标时,内置 <title> 和(或 )<desc>,使 SVG 图标具有可访问性名称:

HTML
<svg class="sy-only">
    <symbol id="search" viewBox="0 0 512 512">
        <title>Search</title>
        <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
    </symbol>

    <symbol id="setting" viewBox="0 0 512 512">
        <title>Setting</title>
        <path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/>
    </symbol>

    <symbol id="home" viewBox="0 0 576 512">
        <title>Home</title>
        <path d="M543.8 287.6c17 0 32-14 32-32.1c1-9-3-17-11-24L512 185V64c0-17.7-14.3-32-32-32H448c-17.7 0-32 14.3-32 32v36.7L309.5 7c-6-5-14-7-21-7s-15 1-22 8L10 231.5c-7 7-10 15-10 24c0 18 14 32.1 32 32.1h32v69.7c-.1 .9-.1 1.8-.1 2.8V472c0 22.1 17.9 40 40 40h16c1.2 0 2.4-.1 3.6-.2c1.5 .1 3 .2 4.5 .2H160h24c22.1 0 40-17.9 40-40V448 384c0-17.7 14.3-32 32-32h64c17.7 0 32 14.3 32 32v64 24c0 22.1 17.9 40 40 40h24 32.5c1.4 0 2.8 0 4.2-.1c1.1 .1 2.2 .1 3.3 .1h16c22.1 0 40-17.9 40-40V455.8c.3-2.6 .5-5.3 .5-8.1l-.7-160.2h32z"/>
    </symbol>
</svg>

但是,我不建议这么使用。以代码中的“放大镜”这个图标为例,当它放在不同的上下文中时,所代表的含义就有可能不同。它有可能是“显示搜索结果”,也有可能是“提交搜索查询”。因此,你的文本标签应该是“显示搜索结果”和“提交搜索查询”,而不是“搜索”(太通用了),千万别写“放大镜图标”,这是非常不好的做法(仅描述了图标的视觉效果,并没有表达图标在上下文中的含义)。这意味着,如果你在 <symbol> 中使用 <title> 对“放大镜”图标进行任何描述,它都很难与上下文所表达的意思相匹配。

其更好的做法是,在使用 <use> 引用 <symbol> 创建的图标实例的时候,使用 <title> 给图标创建可访问名称更为妥当:

HTML
<button type="button">
    <svg role="img" aria-labelledby="a11y-search" focusable="false" class="icon--search">
        <title id="a11y-search">Search</title>
        <use href="#search" />
    </svg>
</button>

<a href="#">
    <svg aria-labelledby="a11y-home" focusable="false" role="img" class="icon--home">
        <title id="a11y-home">Jump to the Home</title>
        <use xlink:href="#icon-angle-down" />
    </svg>
</a>

小结

我们主要以按钮图标为例,讲解了多种为 SVG 图标创建无障碍名称的不同方法。然而,这些方法并不仅限于按钮图标,还可以扩展应用于任何 SVG 图形的无障碍创建。换句话说,可以根据具体的上下文和场景,选择课程中提到的任意一种方法为 SVG 图形创建无障碍名称。