在开发Web应用程序时,我意识到如果我在contenteditable="true"
元素上设置label
,几乎所有浏览器(包括IE 10和11)都可以将焦点设置为除Firefox之外的label
元素。
在研究更多时,我发现这种行为仅适用于某些元素,包括label
元素,而它适用于其他像h4
,p
和span
。
我已经为想要试试这个的人创造了一个JS Bin。
任何人都可以解释这是否是其他浏览器忽略的预期行为或者是Firefox中的错误?
PS:我的规格是Windows 10 x64和Firefox 66.0.1 x64。
function focusId(id) {
document.getElementById(id).focus();
}
<label id="label" contenteditable="true" tabindex="0">Label</label>
<h4 id="h4" contenteditable="true" tabindex="0">H4</h4>
<p id="p" contenteditable="true" tabindex="0">Paragraph</p>
<span id="span" contenteditable="true" tabindex="0">Span</span>
<hr />
<button onclick="focusId('label')">Label</button>
<button onclick="focusId('h4')">H4</button>
<button onclick="focusId('p')">Paragraph</button>
<button onclick="focusId('span')">span</button>
TL; DR:在HTML规范中不允许使用<label>
元素和contenteditable
属性,但视浏览器而定会导致意外行为。
我不能确定为什么它不起作用,但我很确定label
元素不应该以这种方式使用,这可能会导致这个问题。
让我们暂时忘记contenteditable
,然后想想<label>
元素是如何工作的。
作为mentioned in the HTML specification:
针对标签元素的交互式内容后代的事件的标签元素的激活行为以及这些交互式内容后代的任何后代必须无所作为。
从我的角度来看,浏览器会尝试将每个交互事件(focus
作为其中之一)转发到标签的第一个交互式内容或for
属性中使用的元素。当人们想要关注标签时,他们真正的意思是请关注与此标签相关联的表单元素。
因此,如果我们要在<label>
中插入一个可标记元素,那么在标签上调用.focus()
应该会导致可聚焦元素被聚焦,而不是标签。
See this example on JS Bin。在Firefox和Chrome上,结果将是聚焦元素将是输入而不是标签。
一些元素(不是所有元素与形式相关)被归类为可标记元素。这些元素可以与标签元素相关联。
按钮输入(如果类型属性不处于隐藏状态)仪表输出进度选择textarea
关于这一点,并且由于在您提供的示例中没有与<label>
关联的可标记内容,因此预期结果应该是什么都不做。
但现在出现了contenteditable
属性,它通过tab
和指针点击使元素可以聚焦。
这完全违背了将<label>
事件重定向到目标的想法,因为它需要保留和转发这些事件。
合法的问题是:浏览器应该如何处理这两种行为?
好吧,这将是令人失望的,但我想这取决于每个浏览器的边缘情况的实现。我甚至不能说其中一个人是否正确行事。从我的角度来看,Firefox对HTML标签元素规范似乎更严格,而Chromium允许更频繁地使用交互。
从可访问性的角度来看,我倾向于认为Firefox正在做得更好,因为访问表单元素始终是一个完全阻止,而编辑文本可能不是。当然,这取决于你对标签内容的处理方式,这更直观而非经过验证的事实。
所以我的建议是不要使用<label>
来实现你想要实现的目标。
由于你似乎没有任何表单元素,使用<span>
可以完成这项工作,并且在语义上会更好。没有标签的标签只不过是文字。
如果你负担得起,甚至是<textarea>
。
如果你真的需要一个标注文本,它将焦点放在表单元素上但仍然可以编辑,那么问问自己,你需要优先考虑什么。使用指针激活时,您是希望聚焦表单元素还是编辑文本?一个<button>
样式为简单的文本可以做到这一点,并由你决定哪些事件触发其他表单元素集中。并不是说你会有严重的可访问性问题,这不是我推荐的。