如何使没有href属性的链接具有可访问性?

14
我所工作的网站正在使用第三方脚本,它会用<a>替换掉一些<a href="">。由于脚本的另一个部分,链接仍然有效,但用户代理程序不再将其视为链接。
我可以通过添加tabindex="0"来将它们恢复到选项卡导航顺序,但如何使辅助技术将它们作为链接进行公告或包括在页面上所有链接的列表中?
添加role="link"是否有所帮助?
我正在推动第三方改进他们的脚本,以便保留href。但在此期间,我应该如何修复造成的损坏?
我无法像之前那样添加hrefhref="#",因为第三方代码将不再起作用。我希望他们改进代码,这样我就可以这样做,但现在我需要使链接在没有 'href' 的情况下可访问。

我认为你需要提供链接如何运作的示例,无论如何......你会想要从存储js-action的原始href获取它。 - Steen
如果我将href属性添加回链接中,第三方使用的自定义内容和跟踪链接的代码将无法正常工作。我无法控制此代码,但为了满足任何想要查看它的人的好奇心,这是链接:http://jsfiddle.net/eNjnu/ - Steve Pugh
我想知道你能否透露涉及到的第三方?或者更多地揭示它如何处理链接上的点击 - 它是否有其他假设? - BrendanMcK
2个回答

10
为了让一个非href的标签像一个真正的链接一样(并且具有可访问性),你需要添加role="link", tabindex="0",将其样式设为与真实链接相似,并且添加键盘事件处理代码以使回车键能够触发点击事件。
只加上role="link"是不够的。虽然屏幕阅读器可能会将其报告为链接,但如果没有tabindex="0"和适当的视觉样式,一个有视力的用户将无法通过Tab键定位到它,而且如果没有键盘事件处理程序,那么只有鼠标用户才能单击它。 (技术上说,屏幕阅读器用户通常有模拟鼠标单击的热键,但仅有键盘的有视力用户通常没有这个选项,因此不要依赖它。)
另外,如果(非常大的如果!)你使用的脚本允许的话,你可以在原始标签中嵌入一个“键盘点击源”
标签,如下所示:
<a>foo</a>

你需要将它替换为:

<a><a class='shim' href="javascript:void(0)">foo</a></a>

(如果您需要执行后面描述的事件操作,则只需要使用class='shim'。)您可以使用类似于以下内容的jQuery来完成此操作:(借鉴Jack的答案)

$("a:not([href])").wrapInner("<a class='shim' href='javascript:void(0)'></a>")
这是如何运作的:内部新添加的<a ...>具有一个href,因此它被公开为链接并且可以通过Tab键聚焦。更重要的是,如果用户使用Tab键将焦点移动到它并按下回车键,那么默认的A行为会将该键盘输入转换为click事件。这个特定的A具有返回undefined/void(0)的href,因此不会发生实际的导航,但点击事件仍将冒泡到原始的A上,从而使其可以对其进行操作。
(这是一种很好的模式,用于允许某些父元素-通常是DIV或类似物-处理点击事件,添加一个可聚焦的子A,可以从键盘源获取点击事件,从而使您的UI既可以使用鼠标也可以使用键盘。)
这里的一个重要限制条件是假设您的原始脚本不关心事件的target。如果该脚本确实检查了这一点,当它看到来自shim A而不是原始A的点击事件时,它会感到困惑。解决此问题的一种方法是捕获并重新引发事件,这可能会很棘手,并且可能仅适用于最近的浏览器-例如使用以下内容:
// 'shim' class used so we can do this:
$("a.shim").click(function(e) {
    e.preventDefault();
    e.stopPropagation();

    // the following works if listener using jQuery or is setting onclick directly, otherwise...
    // $(e.target).parent().click();.

    // More general way to raise events; may need alternate for IE<9
    var e2 = document.createEvent("UIEvents");
    e2.initUIEvent("click", true, true, window, 1);
    e.target.parentNode.dispatchEvent(e2)
});

看起来可以正常工作了。我需要将它包装在一个计时器中,因为第三方脚本会响应它发起的 AJAX 调用而对页面进行更改,但除此之外,它工作得非常好。非常感谢。 - Steve Pugh
很酷,很高兴它似乎可以工作。你需要做任何事件相关的事情吗?还是“事件源”A链接就足够了?请确保让第三方知道他们的可访问性问题;请记住,虽然您知道这是一个问题并且有解决方法,但使用他们的代码的其他人可能没有意识到这一点,因此最终会得到不必要的无法访问的页面。上面的代码是一个解决方法,而不是一个修复方法。 - BrendanMcK
1
Shim 的想法非常聪明,但它使用了无效的 HTML。<a> 不允许包含嵌套的 <a>(https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element:concept-element-content-model),如果您需要一个干净的 WCAG 报告,它将失败于 4.1.1。但仍然很酷。我的首选是使用 @BrendanMcK 最初提到的 roletabindex 和事件处理程序。 - slugolicious

1

虽然这不太美观,但你可以使用jQuery获取所有没有href属性的锚点,如下所示:

$("a:not([href])")

您可以将这些链接上的href属性设置为“#”,这样它们就会像普通链接一样工作。 这里是一个可用的JSFiddle 很抱歉用jQuery解决方案来回复您,但使用常规JavaScript会更加冗长。
另一种方法是给锚点分配一个角色,然后通过这种方式选择它们:
$("a[role='link']")

Jack,添加href="#"会破坏链接。如果代码拦截了标准的链接点击,那么就不会有问题。但它没有这样做,它依赖于没有href来完成它的工作。我讨厌写得很糟糕的第三方JavaScript。 :-( - Steve Pugh
啊,非常抱歉,我没有意识到。有没有其他的脚本可用,或者你能否编辑原始脚本?这个脚本听起来很麻烦! - Jack Franklin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接