如何通过制表结构使可点击的<div>可访问?

35

我正在进行一个需要使用 <div> onclick 事件的项目。主要功能已经实现了,但是有一个问题。我需要在用户切换到 <div> 并按下 Enter 键时触发 onclick 事件。我为 <div> 添加了 tabindex 属性,这使它可以获取焦点,但是当用户按下 Enter 键(或其他任何键)时,没有任何反应。

有人能帮助我吗?或者我的要求甚至不可能实现吗?

这里是一个 jsfiddle 演示我的问题。 http://jsfiddle.net/logiwan992/suwq7r09/

非常感谢您提前的帮助。


请发送您的代码。!!! - Mxx persian
了解关于 .focus() 的内容。 - D4V1D
把那个 div 放在一个锚点标签里面,这样更语义化,也会简化你的代码。 - Matthew Darnell
1
@MatthewDarnell 在这种情况下使用锚点更语义化吗? - Jacob
@MatthewDarnell 我明白了。你确实提出了让代码更简单的好理由。但是你怎么知道OP想要div在语义上等同于锚点呢?他没有提到使用它来链接资源,这正是锚点的用途,所以这并不会更加语义化。 - Jacob
显示剩余6条评论
6个回答

62

我注意到这个问题被标记为WCAG和“可访问性”。

因此,您的答案是“不要那样做”。本页上的其他答案都可以正常工作,除了需要它正常工作的人,即使用屏幕阅读器或其他辅助技术的人。这里没有任何基于JavaScript的解决方案符合WCAG标准。

你需要的是一个 <button>。这将为您免费提供tabindex和键盘控制功能。

您还可以通过添加ARIA标记将 <div> 用作 <button> (虽然最好和更容易的方法是使用已经具有所需功能的标记)。

如果绝对必要,介绍如何使用ARIA创建伪按钮的好方法在这里: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_button_role

其要点是,您需要添加 role="button" 属性,并手动管理 aria-pressed 属性的状态(通过捕获JavaScript中的按键事件和点击事件;其他答案已经详细介绍了这一点,因此我不会再重复详细信息)


6
问题在于我正在处理遗留代码。如果我将<div>改为<button>,那么所有的样式都会完全混乱。我不知道ARIA标记,但您能解释一下我如何使用它吗?我同意“最好”的选择是将其更改为 <button>。最终我可能会这样做,但需要做更多的工作。 - lfitzgibbons
5
如果你在处理遗留代码,那我敢打赌整个代码都很难读懂。 - Jacob
2
@Logiwan992: 一个 <button> 可以包含任何标记,所以也许你可以在现有的 <div> 周围包装一个按钮标签,而不是用按钮替换该 div。 - Stephen P
我注意到这个问题被标记为WCAG和“可访问性”。因此,你的问题的答案是“不要那样做”。哦,天啊,你读懂了我的想法... - Adam
@Logiwan992 我添加了一些关于ARIA的信息--我真的怀疑你会发现使用<button>并修复CSS比在<div>中重新实现它要少些工作,但是因人而异。 - Daniel Beck
6
我最终将其更改为一个<button>。感谢你的帮助,我认为这是最好的答案。 - lfitzgibbons

3

只要正确指定了ARIA标签、角色和键盘事件,让<div>像按钮一样工作是完全可以的。这就是ARIA的全部意义。

我确实同意,尽可能使用原生html元素。这是ARIA使用的第一条规则-http://www.w3.org/TR/aria-in-html/#notes-on-aria-use-in-html。但我理解这并非总是可能的。

有提到使用focus()。那是不正确的。focus()用于将焦点移动到对象上,而不是用于处理事件。或许他们是指onFocus(),这是当对象接收到焦点时触发的事件,但仍然不是正确的事件捕获方式。你不希望一个按钮(无论是作为<div>还是<button>实现)因为你按Tab键到达它而执行其功能。用户必须点击或按Enter/空格键。

请查看关于按钮键盘行为的创作实践http://www.w3.org/TR/wai-aria-practices/#button,以及讨论键盘事件的部分http://www.w3.org/TR/wai-aria-practices/#focus_tabindex。特别要注意的是,不应该依赖于keypress。并非所有浏览器都会发送该事件。
每次按键时,可能会发生三种可能的事件:keydown、keypress和keyup。keydown和keyup在所有浏览器上都受支持,并且可以访问event.keyCode。keypress在一些浏览器上受支持,并且可以访问event.charCode。
keyCode和charCode之间存在显着的差异,特别是如果您尝试实现快捷键,例如Ctrl+/。许多非美国键盘在键盘上的不同位置具有特殊键,并且您会获得不同的keyCodes。但这是另一个讨论的话题。

1

1
尝试在该div上绑定keypress事件,并检测是否按下了Enter键(其代码编号为13)。
var div = document.getElementsByTagName('div');
div[0].addEventListener('keypress', function(e) {
    if(e.keyCode == 13) {
        alert('div focused');   
    }
});

工作中的JSFiddle


你也可以使用jQuery:

jQuery(function($) {

    $('div').on('keypress', function(e) {
        if(e.keyCode == 13) {
            alert('div focused'); 
        }
    });

});

工作中的JSFiddle


@ochi:好的,我没有注意到 OP 标签中没有 jQuery。 - D4V1D
如果可能的话,我希望它能够在没有JQuery的情况下工作,但我确实希望它能够使用ENTER键。首先,div通过TAB获得焦点,然后ENTER键就像单击div一样。 - lfitzgibbons
@ochi:当然可以,但是 OP 想要检测在 div 上按下 Enter 键的操作。元素必须获得焦点才能触发事件处理程序,因此无需检测 focusTAB 键。 - D4V1D
如果它可以使用“Enter”键工作,那么在使用键盘导航时,“Space”键也应该能够激活按钮或链接之一。 - Stephen P
@StephenP:我对无障碍性并不是很了解。下次,我会花更多时间阅读与问题相关的标签 :) - D4V1D
显示剩余2条评论

0
给元素添加role="button"和tabindex="0",使其可聚焦。然后在任何聚焦/活动的按钮上检测回车或空格键。将其转换为点击事件。
以下是实现此功能的HTML和jQuery代码。您只需添加一次即可,它适用于所有role=button元素。
<div role="button" tabindex="0">Do that thing</div>

$("body").on("keypress","[role='button']", function(e) { 
     if(e.keyCode == 13 || e.keyCode == 32){ // 13=enter, 32=spacebar
         $(this).click();
         return false;
     }
})

我实际上是这样做的,而不是使用适当的

-2

Use the same event handler for both events. If the event is keypress verify the key pressed is the Enter key before executing.

var divButton = document.querySelector('#div-button');

divButton.addEventListener('click', activate);
divButton.addEventListener('keypress', activate);

function activate(e) {
  if (e.type === 'keypress' && e.keyCode == 13) {
    alert('activated the div'); 
  }
};
div {
    outline: 1px solid black;
}

div:focus {
    outline: 1px solid red;
}
<div id="div-button" tabindex="0">
    <h1>This is my div!</h1>
</div>    


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