首页 > 解决方案 > Firefox 无法使用 JavaScript 将焦点设置到某些 DOM 元素

问题描述

在开发 web 应用程序时,我意识到如果我contenteditable="true"在一个label元素上设置,几乎所有浏览器包括 IE 10 和 11 都可以将焦点设置到该label元素上,除了 Firefox。

在进行更多调查时,我发现此行为仅适用于某些元素,包括label元素,而对于其他元素(如h4,pspan.

我为任何想尝试这个的人创建了一个JS Bin 。

谁能解释这是其他浏览器忽略的预期行为还是Firefox中的错误?

PS:我的规格是Windows 10 x64Firefox 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>

标签: javascriptfirefoxdomcontenteditable

解决方案


TL;DR : HTML 规范中不允许使用<label>元素和属性,但取决于浏览器会导致意外行为。contenteditable


我不能确定为什么它不起作用,但我很确定该label元素不应该以这种方式使用,这可能会导致这个问题。

让我们暂时忘掉contenteditable,想想<label>元素是如何工作的。

HTML 规范中所述

对于针对标签元素的交互式内容后代以及这些交互式内容后代的任何后代的事件,标签元素的激活行为必须不执行任何操作。

从我的角度来看,浏览器会尝试将每个交互事件(focus作为其中之一)中继到标签的第一个交互内容或for属性中使用的元素。当一个人想要关注一个标签时,他们真正的意思是请关注与这个标签关联的表单元素

因此,如果我们要在 a 中插入一个可标记元素<label>,那么调用.focus()标签应该会导致可标记元素被聚焦,而不是标签。

请参阅 JS Bin 上的此示例。在 Firefox 和 Chrome 上,结果将是焦点元素将是输入,而不是标签。

一些元素(并非所有元素都与表单相关)被归类为可标记元素。这些是可以与标签元素相关联的元素。

按钮输入(如果type属性不处于隐藏状态)仪表输出进度选择textarea

关于这一点,由于<label>您提供的示例中没有与 相关的可标记内容,因此预期的结果应该是什么都不做。

但是现在出现了contenteditable属性,它使元素可以通过tab和指针单击获得焦点。

这完全违背了将<label>事件重定向到目标的想法,因为它需要保留和中继这些事件。

合理的问题是:浏览器应该如何处理这两种行为?

好吧,这将令人失望,但我想这取决于每个浏览器的这种边缘情况的实现。我什至不能说他们中的一个人是否做得对。从我的角度来看,Firefox 似乎对 HTML 标签元素规范更加严格,而 Chromium 允许更宽松地使用交互。

从可访问性的角度来看,我倾向于认为 Firefox 做得更好,因为访问表单元素总是一个完全的障碍,而编辑文本可能不会。当然,这取决于您对标签内容的处理方式,这更像是一种直觉,而不是已证实的事实。


因此,我的建议是不要将 a<label>用于您想要实现的目标。

由于您似乎没有任何表单元素,因此使用 a<span>可以完成这项工作并且在语义上会更好。一个没有任何标签的标签只不过是一个文本。
或者,<textarea>如果你负担得起的话。

如果你真的需要一个标签式的文本来关注表单元素但仍然是可编辑的,问问自己你需要优先考虑什么。当使用指针激活时,您希望表单元素获得焦点还是编辑文本?一个<button>样式简单的文本可以解决问题,由您决定哪些事件触发另一个表单元素成为焦点。并不是说这样做会遇到严重的可访问性问题,这不是我推荐的。


推荐阅读