Html tabIndex 不会使用 Tab 键使标签可聚焦

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27550415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 03:13:42  来源:igfitidea点击:

tabIndex doesn't make a label focusable using Tab key

html

提问by hon2a

I'm trying to replace checkbox/radio inputs with icons. For this, I need to hide the original checkbox/radio. The problem is, I also want the form to properly support keyboard input, i.e. let the input remain focusable by Tabkey and selectable using Spacebar. Since I'm hiding the input, it cannot be focused, so instead, I'm trying to make its <label>focusable.

我正在尝试用图标替换复选框/收音机输入。为此,我需要隐藏原始复选框/收音机。问题是,我还希望表单正确支持键盘输入,即让输入保持Tab按键可聚焦并使用Spacebar. 因为我隐藏了输入,所以它不能被聚焦,所以相反,我试图让它<label>成为可聚焦的。

This documentationand various other sources led me to believe I can do that using tabindexattribute (corresponding to HTMLElement.tabIndexproperty). However, when I try to assign tabindexto my label, it remains as unfocused as ever, however much I try to Tabto it.

该文档和其他各种来源使我相信我可以使用tabindex属性(对应于HTMLElement.tabIndex属性)来做到这一点。然而,当我尝试分配tabindex给我的标签时,无论我多么努力,它仍然像以前一样没有重点Tab

Why doesn't tabindexmake the label focusable?

为什么不tabindex使标签可聚焦?

The following snippet demonstrates the issue. If you focus the input with your mouse and try focusing the label using Tab, it doesn't work (it focuses the following <span>with tabindexinstead).

以下代码段演示了该问题。如果你注重的输入您的鼠标并尝试使用聚焦的标签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>

(The JavaScript code just allows to see that clicking on the label properly (un)checks the checkbox.)

(JavaScript 代码只允许看到正确单击标签(取消)选中复选框。)

回答by Abhitalks

Why doesn't tabindex make the label focusable?

为什么 tabindex 不能使标签成为焦点?

Short Answer:

简答

  1. Label is focusable.
  2. TabIndex won't make any difference.
  3. Welcome to the world of browser/agent inconsistencies.
  1. 标签是可聚焦的。
  2. TabIndex 不会有任何区别。
  3. 欢迎来到浏览器/代理不一致的世界。

tl;dr;

tl;博士;

The label(Ref)element is very much focusable. Its DOM Interface is HTMLLabelElementwhich derives from HTMLElement(Ref)which in turn implements GlobalEventHandlers(Ref)and hence exposes the focus()method and onfocusevent handler.

label(REF)元素是非常可获得焦点。它的 DOM 接口HTMLLabelElement源自HTMLElement(Ref),而(Ref)又实现了GlobalEventHandlers(Ref),因此公开了focus()方法和onfocus事件处理程序。

The reason you are unable to get hold of proper specification / reference document for labels focus behaviour, is because you might have been looking at HTML5 Specs. Interestingly, HTML5 refs do not state anything relating to that, which adds to the confusion.

您无法获得有关labels 焦点行为的正确规范/参考文档的原因是因为您可能一直在查看 HTML5 规范。有趣的是,HTML5 refs 没有说明任何与此相关的内容,这增加了混淆。

This is mentioned in the HTML 4.01 Ref here: http://www.w3.org/TR/html401/interact/forms.html#h-17.9.1

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

Specifically near the end of section 17.9.1 and just before 17.10:

特别是在第 17.9.1 节末尾和 17.10 节之前:

When a LABEL element receives focus, it passes the focus on to its associated control.

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

Also, elsewhere (I am unable to get hold of that part of the ref) I have read that it depends on the implementing agent. (Don't take my word for that, am not too sure).

另外,在其他地方(我无法掌握 ref 的那部分)我已经读到这取决于执行代理。(不要相信我的话,我不太确定)。

However, what it means is that when you focusa label(or a labelreceived a focus), that focusis passed on to its associated labeleable control. This will not result in two different focuses, but one focuson the input(in your case a checkbox). Because of this behaviour, tabindexproperty cannot play a role.

但是,这意味着当您focusa label(或 alabel收到 a focus)时,focus将其传递给其关联的可标记控件。这不会导致两个不同的focusES,但一focusinput(你的情况复选框)。由于这种行为,tabindex财产不能发挥作用。

There is also a test suite by W3C for website accessibility (WAAG) here: http://www.w3.org/WAI/UA/TS/html401/cp0102/0102-ONFOCUS-ONBLUR-LABEL.htmlwhich, discusses the implementation of onfocusand onblurfor a label. Ideally a keyboard or an assistive technology that emulates the keyboardshould implement this. But...

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

This is where the browser inconsistencies play their role.

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

This can be demonstrated by this example. Check the following snippet in different browsers. (I have tested it against IE-11, GC-39 and FF-34. All of them behave differently.)

这可以通过这个例子来证明。在不同的浏览器中检查以下代码段。(我已经针对 IE-11、GC-39 和 FF-34 对其进行了测试。它们的行为都不同。)

  1. Click the button "Focus Label"
  2. It should focus the label, then pass the focus and highlight its associated checkbox outline in blue.
  3. Chrome-v39 works. IE-v11 it doesn't (somehow html and body do respond to :focus). FF-v34 it works.
  1. 单击按钮“焦点标签
  2. 它应该聚焦标签,然后传递焦点并以蓝色突出显示其关联的复选框轮廓。
  3. Chrome-v39 有效。IE-v11 没有(不知何故 html 和 body 确实响应:focus)。FF-v34 它有效。

Talking about browser inconsistencies, try using the "access key" L. Some browsers will focus the checkbox whereas some will click it i.e. pass the action to it.

谈到浏览器不一致,请尝试使用“访问密钥” L。有些浏览器会聚焦复选框,而有些浏览器会点击它,即将动作传递给它。

Here is a fiddleto test it: http://jsfiddle.net/abhitalks/ff0xds4z/2/

这是一个测试它的小提琴http: //jsfiddle.net/abhitalks/ff0xds4z/2/

Here is a snippet:

这是一个片段

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" />

Hope that clears up your doubts.

希望能解开你的疑惑。

.

.



Your problem:

你的问题:

Now focussing (sic) on your original problem of not being able to focus a label, because you want to style a checkbox differently by placing an icon kind of thing in its place.

现在focus唱(原文如此)关于无法聚焦标签的原始问题,因为您想通过在其位置放置图标类的东西来以不同的方式设置复选框的样式。

In order to do that, one option for you is to nothide it completely by doing a display:none;. Rather, make it 1x1 pixel and shove it under your icon. This way it will still receive focus naturally and yet be effectively hidden.

为了做到这一点,您的一个选择是通过执行display:none;. 相反,将其设为 1x1 像素并将其推到您的图标下方。通过这种方式,它仍然会自然地获得焦点,同时又被有效地隐藏起来。

For example, if your icons are a checkmarkand a cross, then change the position of the checkbox and make the icons out of ::beforeor ::afterpseudo-elements on the label. That will cause the checkbox to still receive focus, and make the icon respond to that. That will give the apparent illusion of the icon taking the focus.

例如,如果您的图标是一个复选标记和一个叉号,则更改复选框的位置并使图标脱离标签上的::before::after伪元素。这将导致复选框仍然接收焦点,并使图标对此做出响应。这会给图标带来焦点的明显错觉。

Demo Fiddle: http://jsfiddle.net/abhitalks/v0vxcw77/

演示小提琴:http: //jsfiddle.net/abhitalks/v0vxcw77/

Snippet:

片段

div.chkGroup { position: relative; }
input#chk {
    position: absolute;
    width: 1px; height: 1px;
    margin: 0; margin-top: 4px; outline: none;
    border: 1px solid transparent; background-color: transparent;
}
label::before {
    content: '14';
    position: relative;
    width: 18px; height: 18px;
    background-color: #fff;
    margin-right: 8px; padding: 2px;
    display: inline-block; 
    border: 1px solid transparent;
}
input#chk:checked + label::before {
    content: '16';
}
input#chk:focus + label::before {
    border: 1px solid #00f;
}
<input id="txt" type="text" value="input" /><br /><br />
<div class="chkGroup">
    <input id="chk" type="checkbox" />
    <label for="chk" accesskey="L">Checkbox</label>
</div>

.

.

回答by Heretic Monkey

Edit: The following was a misreading of the spec:

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

Looking that the full specification, you'll see that there is something called tabindex focus flag, which defines if the tabindexattribute will actually make the field "tabbable". The labelelement is missing from that list of suggested elements.

But then again, so is the spanelement, so go figure :).

查看完整规范,您会看到有一个叫做tabindex focus flag 的东西,它定义了该tabindex属性是否真正使字段“可选项卡”。该label元件是由建议元素列表中缺少。

但话又说回来,span元素也是如此,所以去图:)。

That said, yYou can make the label text focusable by wrapping the whole thing in an another element, or using some JavaScript to force the issue. Unfortunately, wrapping (here in an anchor) can men a fair amount of extra work in CSS and JS to get working like a normal labelelement.

也就是说,你您可以通过将整个内容包装在另一个元素中,或使用一些 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>

回答by Frank Nocke

As previous posters said: Label focus always goes directly to the input element.

正如之前的海报所说: 标签焦点始终直接指向输入元素。

Quite an annoyance if somebody has fancy (but fake) checkboxes, hiding the original ones, with an actual focus for keyboard navigation nowhere to be seen.

如果有人有花哨的(但假的)复选框,隐藏原始复选框,而键盘导航的实际焦点无处可见,那就太烦人了。

best solution I can think of: javascript.

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

Style-away the actual focus, in favor of a fake one:

风格远离实际焦点,支持假焦点:

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

and watch for changes on the (in many scenarios visibly hidden) original checkbox:

并注意(在许多情况下明显隐藏)原始复选框的变化:

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

Full jsfiddle here.

完整的jsfiddle 在这里

回答by Besworks

Since this old post is one of the top google results for html label tabindexI want to add my very simple working solution. As @Abhitalks mentioned in the accepted answer, the focus of a label is passed to it's associated control. So to bypass this behavior, just add a tabindexto the label and use event.preventDefault()in a focusEventListener.

由于这篇旧帖子是html 标签 tabindex的顶级谷歌搜索结果之一,我想添加我的非常简单的工作解决方案。正如@Abhitalks 在接受的答案中提到的,标签的焦点被传递给它的关联控件。因此,要绕过此行为,只需将 a 添加tabindex到标签并event.preventDefault()在 a 中使用focusEventListener

@Heretic Monkey kind of had the right idea in his answer but you don't need a wrapper element to achieve this. You will, however, need to manually forward any required keystrokes (like spacebar) through.

@Heretic Monkey 在他的回答中有正确的想法,但您不需要包装器元素来实现这一点。但是,您需要手动转发任何所需的按键(如空格键)。

For example:

例如:

'use strict';

let field = document.getElementById('hidden-file-chooser');
let label = document.querySelector('label[for=hidden-file-chooser]');

// prevent focus passing
label.addEventListener('focus', event => {
  event.preventDefault();
});

// activate using spacebar
label.addEventListener('keyup', event => {
  if (event.keyCode == 32) {
    field.click();
  }
});
#hidden-file-chooser {
  display: none;
}

input[type=text] {
  display: block;
  width: 20rem;
  padding: 0.5rem;
}

label[for=hidden-file-chooser] {
  display: inline-block;
  background: deepskyblue;
  margin: 1rem;
  padding: 0.5rem 1rem;
  border: 0;
  border-radius: 0.2rem;
  box-shadow: 0 0 0.5rem 0 rgba(0,0,0,0.7);
  cursor: pointer;
}
<input type="text" placeholder="Click here and start tabbing through ...">

<input id="hidden-file-chooser" type="file">
<label for="hidden-file-chooser" tabindex="0"> Select a File </label>

<input type="text" placeholder="... then shift+tab to go back.">

P.S: I used input[type=file]in my example because that's what I was working on when I ran across this issue. The same principles apply to any input type.

PS:我input[type=file]在我的例子中使用,因为这就是我遇到这个问题时正在做的事情。相同的原则适用于任何输入类型。

回答by Femi Ojemuyiwa

For input type radio or checkbox:

对于输入类型单选或复选框:

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

and the Js above does the trick sweetly.

上面的 Js 巧妙地解决了这个问题。