tabIndex不使用Tab键使标签可以聚焦

我试图用图标replacecheckbox/收音机input。 为此,我需要隐藏原来的checkbox/收音机。 问题是,我也希望窗体正确支持键盘input,即让input保持Tab键焦点和可选Spacebar 。 因为我隐藏了input,所以不能集中注意力,所以我试图使它的<label>可调焦。

这个文档和各种其他来源使我相信我可以使用tabindex属性(对应于HTMLElement.tabIndex属性)来做到这一点。 但是,当我尝试将tabindex分配给我的标签时,它仍然像以往一样不专心,无论我尝试Tab还是如此。

为什么不tabindex使标签可重点?

以下片段演示了这个问题。 如果你用鼠标把input集中在一起,并尝试使用Tab对标签进行聚焦,它将不起作用(它会将下面的<span>tabindex来代替)。

 document.getElementById('checkbox').addEventListener('change', function (event) { document.getElementById('val').innerHTML = event.target.checked; }); 
 <div> <input type="text" value="input"> </div> <div> <label tabindex="0"> <input type="checkbox" id="checkbox" style="display:none;"> checkbox: <span id="val">false</span> </label> </div> <span tabindex="0">span with tabindex</span> 

(JavaScript代码只是允许看到正确点击标签(联合国)检查checkbox。)

为什么不tabindex使标签可重点?

简答

  1. 标签是可以聚焦的。
  2. TabIndex不会有任何区别。
  3. 欢迎来到浏览器/代理不一致的世界。

TL;博士;

label (Ref)元素非常适合。 它的DOM接口是HTMLLabelElement ,它来自HTMLElement (Ref) ,而HTMLElement (Ref)又实现了GlobalEventHandlers (Ref) ,从而暴露了focus()方法和onfocus事件处理程序。

你无法得到适当的规范/参考文件label的焦点行为的原因,因为你可能一直在看HTML5规格。 有趣的是,HTML5的参考并没有说明任何有关的,这增加了混乱。

这在HTML 4.01 Ref中提到: http : //www.w3.org/TR/html401/interact/forms.html#h-17.9.1

特别是在第17.9.1节的末尾以及17.10之前:

当LABEL元素获得焦点时,它将焦点传递给其关联的控件。

另外,在其他地方( 我无法掌握裁判的这一部分 )我已经读过,这取决于执行代理。 ( 不要拿我的话,我不太确定 )。

然而,这意味着当你focus一个label (或者一个label获得focus )时,这个focus被传递给它相关的标签控件。 这不会导致两个不同的focus ,但一个focusinput (在你的情况下一个checkbox)。 由于这种行为, tabindex属性不能发挥作用。

W3C还有一个testing套件,用于网站访问(WAAG): http : //www.w3.org/WAI/UA/TS/html401/cp0102/0102-ONFOCUS-ONBLUR-LABEL.html ,其中讨论了实现onfocusonblurlabel 。 理想情况下,模拟键盘键盘或辅助技术应该实现这一点。 但…

这是浏览器不一致性发挥作用的地方。

这可以通过这个例子来certificate。 在不同的浏览器中检查以下片段。 (我已经对IE-11,GC-39和FF-34进行了testing,它们的performance都不一样)。

  1. 点击button“ 焦点标签
  2. 它应该关注标签,然后传递焦点并以蓝色突出显示其关联的checkbox大纲。
  3. Chrome-v39的作品。 IE-V11它不(以某种方式HTML和身体做回应:重点)。 它的工作原理FF-V34。

在谈到浏览器不一致时,请尝试使用“访问键” L。 有些浏览器会关注checkbox,而有些则会点击它,即将操作传递给它。

这里是一个小提琴来testing它: http : //jsfiddle.net/abhitalks/ff0xds4z/2/

这是一个片段

 label = $("label").first(); $("#btn").on("click", function() { label.focus(); }); 
 * { margin: 8px; } .highlight { background-color: yellow; } :focus { outline: 2px solid blue; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input id="txt" type="text" value="input" /><br /> <label for="chk" accesskey="L">Checkbox: </label> <input id="chk" type="checkbox" /><br /> <input id="btn" type="button" value="Focus Label" /> 

编辑 :以下是规范的误读:

看看完整的规范 ,你会看到有一些叫做tabindex焦点标志 ,它定义了tabindex属性是否实际上使字段“tabbable”。 build议元素列表中缺lesslabel元素。

但是再次, span元素也是如此,所以去图:)。

这就是说, 您可以通过将整个事物包装在另一个元素中,或者使用一些JavaScript来强制解决问题,从而使标签文本成为可聚焦的。 不幸的是,包装(在这里是一个锚点)可以在CSS和JS中进行相当多的额外工作,以像普通label元素一样工作。

 document.getElementById('checkbox').addEventListener('change', function(event) { document.getElementById('val').innerHTML = event.target.checked; }); document.getElementsByClassName('label')[0].addEventListener('click', function(event) { event.target.getElementsByTagName('label')[0].click(); event.preventDefault(); }); document.getElementsByClassName('label')[0].addEventListener('keypress', function(event) { if ((event.key || event.which || event.keyCode) === 32) { event.target.getElementsByTagName('label')[0].click(); event.preventDefault(); } }); 
 .label, .label:visited, .label:hover, .label:active { text-decoration: none; color: black; } 
 <div> <input type="text" value="input"> </div> <div> <a class="label" href="#"> <label tabindex="0"> <input type="checkbox" id="checkbox" style="display:none;">checkbox: <span id="val">false</span> </label> </a> </div> <span tabindex="0">span with tabindex</span> 

正如之前的海报所说: 标签焦点总是直接进入input元素。

如果有人喜欢(但假的)checkbox,隐藏原来的,真实的焦点,键盘导航无处可见,这是一个非常烦恼。

我能想到的最佳解决scheme:javascript。

风格 – 实际的重点,有利于一个假的:

  input[type=checkbox]:focus { outline: none; } .pseudo-focus { outline: 2px solid blue; } 

并观察(在许多情况下可见隐藏)原来的checkbox的变化:

  $('input[type=checkbox') .focus( function() { $(this).closest('label').addClass('pseudo-focus'); }) .blur( function() { $(this).closest('label').removeClass('pseudo-focus'); }); 

完整的jsfiddle在这里 。

对于inputtypes收音机或checkbox:

 opacity: 0; height: 0; width: 0; min-height: 0; line-height: 0; margin: 0; padding: 0; border: 0 none; 

而上面的Js甜蜜地诀窍。