使用背景图片更正 link 的 a11y 声明

Correct a11y declaration for a link with just a background image

我正在尝试为 links 找到改进 a11y 的最佳方法,这些 links 仅使用跨度内的背景图像构建(老式的大量图标 spritesheet 方法)。它们是大型网站的一部分,现在更改整个图标系统并不现实。

我们基本上就是这两个不同的link;

第一个是问题:

<a href="#" aria-label="Functionality Description">
  <span class="icon-functionality"></span>
</a>

另一个 link 样式中有文字,所以应该没问题。

<a href="#" aria-label="Functionality Description">
   <span class="icon-text">Functionality</span>
   <span class="icon-functionality"></span>
</a>

试图找出在第一种情况下我们应该做什么,我找到了一个我不确定的解决方案;给包含背景的 span role="img" 和一个空的 alt 属性。

这样,anchor 里面就有图片了,通过空 alt 属性,屏幕 reader 会理解为装饰图片。在这种情况下,reader 将 aria-label 关联到 'understand' 功能的锚点。

<a href="#" aria-label="Functionality Description">
  <span class="icon-functionality" role="img" alt></span>
</a>

虽然我知道这并不理想,而且从长远来看我们可能想要更改整个图标系统,但这足以提供一个体面的 a11y 吗?你怎么看?

欢迎所有建议。非常感谢!

编辑以添加给定 Siteimprove 错误的屏幕截图:

简答

当前使用 aria-labels 在整个网站上实施没有任何问题。如果 aria-label 未被读取,您的改进示例实际上在可访问性方面更差。

更长的答案

屏幕 readers 不会显示背景图片,并且假定其纯粹是装饰性的。

所以下面的(你的第一个例子)是完全可以接受的:

<a href="#" aria-label="Functionality Description">
  <span class="icon-functionality"></span>
</a>

aria-label 将提供屏幕 reader 需要的所有信息。

在您的第二个示例中,aria-label 无论如何都会覆盖内容,因此 icon-text 与屏幕 reader 无关。

在你的第三个例子中你有同样的事情 aria-label 覆盖内容。

话虽如此,如果您没有 aria-label 具有空 alt 属性是不正确的,它应该是 empty alt 属性被隐藏。 (因此 alt="" 而不是 alt,否则屏幕 reader 将尝试为图像查找名称(这可能会导致意外行为背景图片)。

您现在还使用 role="img" 将背景图像引入了可访问性树(因为它以前会被忽略),因此实际上为您自己做了更多工作。

最佳选择

一个更好的选择是 if you are able to implement that, as it has better compatibility (aria-label isn't 100% supported in all scenarios 令人惊讶)并且视觉上隐藏的文本在纯文本浏览器中有效。

如果你能做到这一点,那么由于兼容性,这是更好的做事方式,但你的 aria-label 方法在 99% 的情况下都很好,所以如果这是难以实施。

在下面的示例中,为了演示目的,我包含了一个内联 SVG,而不是您的背景图像,但关键部分是额外的 <span>visually-hidden class。

a{
    width: 25%;
    display: block;
}

.visually-hidden { 
    border: 0;
    padding: 0;
    margin: 0;
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
    clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
    clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
    white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<a href="#">
  <span class="icon-functionality">
  <!----ignore this SVG it is for demonstration purposes only-->
  <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
        <path fill="#666" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z">
        </path>
    </svg></span>
  <!----This is the key part, use this instead of `aria-label` if you can.-->
  <span class="visually-hidden">Functionality Description</span>
</a>

其他想法

只是一个快速的,但我希望 href="#" 仅用于演示目的。

如果您在网站上发现任何使用 href="#" 的锚点,这是一种反模式并且是可访问性的不良做法。

相反,如果它们执行操作,它们应该是按钮,否则如果它们用于导航,它们应该是有效的 URL。

我只是因为你的 aria-label 说“功能描述”才提出这个问题,这让我觉得你正在为按钮使用锚点。

如果您需要更多关于为什么这对可访问性很重要的信息,我可以 link 为您提供几个答案。