我正在寻找一个HTML元素的明确列表,这些元素可以被聚焦,即在这些元素上调用focus()
时将把它们放入焦点状态。
我正在编写一个jQuery扩展,适用于可以聚焦的元素。我希望这个问题的答案能够让我具体地确定我要定位的元素。
没有一个确定的列表,它由浏览器决定。我们唯一有的标准是根据DOM Level 2 HTML,其规定具有 focus()
方法的元素只有HTMLInputElement
、HTMLSelectElement
、HTMLTextAreaElement
和 HTMLAnchorElement
。这显然排除了HTMLButtonElement
和HTMLAreaElement
。
今天的浏览器在HTMLElement上定义了focus()
,但实际上只有以下元素才会获得焦点:
disabled
(如果尝试会在IE中出错),而文件上传因安全原因具有异常行为tabindex
属性的元素根据浏览器,这个行为可能还会有其他微妙的例外和补充。
这里我有一个基于bobince的回答的CSS选择器,可以选择任何可聚焦的HTML元素:
a[href]:not([tabindex='-1']),
area[href]:not([tabindex='-1']),
input:not([disabled]):not([tabindex='-1']),
select:not([disabled]):not([tabindex='-1']),
textarea:not([disabled]):not([tabindex='-1']),
button:not([disabled]):not([tabindex='-1']),
iframe:not([tabindex='-1']),
[tabindex]:not([tabindex='-1']),
[contentEditable=true]:not([tabindex='-1'])
{
/* your CSS for focusable elements goes here */
}
或者在SASS中更美观一点:
a[href],
area[href],
input:not([disabled]),
select:not([disabled]),
textarea:not([disabled]),
button:not([disabled]),
iframe,
[tabindex],
[contentEditable=true]
{
&:not([tabindex='-1'])
{
/* your SCSS for focusable elements goes here */
}
}
当我在谷歌搜索时,被重定向到这个 Stackoverflow 问题,但这正是我正在寻找的答案,因此我将其作为回答添加了进来。
编辑: 还有一个可聚焦的选择器:
[contentEditable=true]
然而,这种用法非常罕见。
<a href="foo.html">Bar</a>
肯定是可获得焦点的,因为它是一个具有href
属性的a
元素。但是你的选择器并没有包括它。 - jbyrdtabindex="-1"
并不会使元素无法聚焦,只是不能通过按Tab键来聚焦。仍然可以通过单击它或使用HTMLElement.focus()
在编程上获得焦点;同样适用于任何其他负数。请参见:https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex - Lazzaroinput:not([type="hidden"])
,除非你想要选择器聚焦一个在浏览器默认情况下被视觉和屏幕阅读器隐藏的元素。 - Bashu Naimi-Roy$focusable:
'a[href]',
'area[href]',
'button',
'details',
'input',
'iframe',
'select',
'textarea',
// these are actually case sensitive but i'm not listing out all the possible variants
'[contentEditable=""]',
'[contentEditable="true"]',
'[contentEditable="TRUE"]',
'[tabindex]:not([tabindex^="-"])',
':not([disabled])';
我正在创建一个SCSS列表,列出所有可聚焦的元素,因为我认为这可能会对某些人有所帮助,因为这个问题在Google排名中比较靠前。
需要注意几点:
:not([tabindex="-1"])
更改为:not([tabindex^="-"])
,因为生成-2
是完全有可能的。安全起见,对吧?:not([tabindex^="-"])
是完全毫无意义的。当使用[tabindex]:not([tabindex^="-"])
时,它已经包括了您要用:not
否定的所有元素!:not([disabled])
,因为禁用的元素永远不能成为可聚焦的。所以把它添加到每个单独的元素中是无用的。:not([disabled])
的部分是错误的。不相信我?执行 document.querySelectorAll(':not([disabled])')
然后看看会发生什么。未禁用意味着您想要所有已启用的元素。 - Jeff Luyet:not([tabindex^="-"]
的部分。证明:在控制台中尝试运行以下代码:
document.querySelectorAll('a, [tabindex]:not([tabindex="-1"]')[0]
它将选择一个节点,例如 <a href="shouldnt-be-focused" tabindex="-1">nope</a>
就我所知,这是由于误解了这些选择器是由“或”连接而不是“和”,因此一旦遇到 <a> 标签,它就满足了选择器。 - Bashu Naimi-Royfunction focus(el){
el.focus();
return el==document.activeElement;
}
返回值:true = 成功,false = 失败
参考文献: https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentOrShadowRoot/activeElement https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/focus
有一种更加优雅的处理方式:
像下面的示例一样扩展元素原型。 然后你可以这样使用它:
element.isFocusable()
*如果“element”可聚焦,则返回 true ,否则返回 false 。
/**
* Determining if an element can be focused on
* @return {Boolean}
*/
HTMLElement.prototype.isFocusable = function () {
var current = document.activeElement
if (current === this) return true
var protectEvent = (e) => e.stopImmediatePropagation()
this.addEventListener("focus", protectEvent, true)
this.addEventListener("blur", protectEvent, true)
this.focus({preventScroll:true})
var result = document.activeElement === this
this.blur()
if (current) current.focus({preventScroll:true})
this.removeEventListener("focus", protectEvent, true)
this.removeEventListener("blur", protectEvent, true)
return result
}
// A SIMPLE TEST
console.log(document.querySelector('a').isFocusable())
console.log(document.querySelector('a[href]').isFocusable())
<a>Not focusable</a>
<a href="#">Focusable</a>
focusin
、focusout
)注册事件保护器吗?而且,我们不应该也为current
添加事件保护器吗? - aradalvand
element.isContentEditable === true
属性的元素也可获得焦点。 注意,在 IE -10(11+?)中,任何display:block
或table
的元素(如 div、span 等)都可以获得焦点。 - mems