【问题标题】:Which HTML elements can receive focus?哪些 HTML 元素可以接收焦点?
【发布时间】:2010-12-08 15:37:54
【问题描述】:

我正在寻找允许获得焦点的 HTML 元素的明确列表,即当调用 focus() 时哪些元素将成为焦点?

我正在编写一个 jQuery 扩展,它适用于可以聚焦的元素。我希望这个问题的答案能让我具体了解我所针对的元素。

【问题讨论】:

    标签: html focus


    【解决方案1】:

    没有一个明确的列表,这取决于浏览器。我们拥有的唯一标准是DOM Level 2 HTML,根据该标准,唯一具有focus() 方法的元素是 HTMLInputElementHTMLSelectElementHTMLTextAreaElementHTMLAnchorElement。这明显省略了HTMLButtonElementHTMLAreaElement

    今天的浏览器在 HTMLElement 上定义 focus(),但一个元素实际上不会获得焦点,除非它是以下之一:

    • 带有href的HTMLAnchorElement/HTMLAreaElement
    • HTMLInputElement/HTMLSelectElement/HTMLTextAreaElement/HTMLButtonElement 但不是disabled(如果您尝试,IE 实际上会给您一个错误),并且出于安全原因,文件上传有异常行为
    • HTMLIFrameElement(尽管聚焦它并没有什么用处)。可能还有其他嵌入元素,我还没有全部测试过。
    • 任何带有tabindex 的元素

    根据浏览器的不同,此行为可能还有其他细微的例外和补充。

    【讨论】:

    • 我发现了一些有趣的结果:jsfiddle.net/B7gn6 建议我至少在 Chrome 中使用“tabindex”属性是不够的..
    • tabindex 属性“允许作者控制一个元素是否应该是可聚焦的”在 HTML5 中是标准化的:w3.org/TR/html5/… 基本上,值 0 使元素可聚焦,但它的排序最多浏览器。
    • 所有带有element.isContentEditable === true 的元素也是可聚焦的。请注意,IE -10 (11+?) 可以使用显示块或表格(div、span 等)聚焦任何元素。
    • tabindex 为 -1 的元素可以通过 focus 方法以编程方式接收焦点;它只是不能被标签到。
    • …除非 tabindex 为 -1,否则无法聚焦 >> 不正确,如果 tabindex 为 -1,则可以通过 CLICKING 聚焦,但无法通过按“tab”聚焦。 -1 使元素可聚焦,只是它没有按 Tab 键顺序添加。见:jsfiddle.net/0jz0kd1a,先尝试点击元素,然后将tabindex改为0,尝试使用tab。
    【解决方案2】:

    这里我有一个基于 bobinceanswer 的 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 */
        }
    }
    

    我已将其添加为答案,因为当 Google 将我重定向到这个 Stackoverflow 问题时,我正在寻找它。

    编辑:还有一个选择器,它是可聚焦的:

    [contentEditable=true]
    

    但是,这很少使用。

    【讨论】:

    • @TWiStErRob - 您的选择器不针对与@ReeCube 的选择器相同的元素,因为您的选择器不包含没有明确设置 tabindex 的元素。例如<a href="foo.html">Bar</a> 肯定是可聚焦的,因为它是具有href 属性的a 元素。但是您的选择器不包含它。
    • @jbyrd 只是根据 bobince 的声明要求编辑:“......除非 tabindex 是 -1,这使得焦点不可能。”,它永远不应该取代 ReeCube 的答案;查看编辑历史记录。
    • SASS(或 CSS)是为上述问题提供严格答案的合适形式(除非浏览器不一致)。
    • tabindex="-1" 确实 not 使元素无法聚焦,只是无法通过 Tab 键聚焦。它仍然可以通过单击它或使用HTMLElement.focus() 以编程方式获得焦点;任何其他负数相同。见:developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/…
    • 我建议使用input:not([type="hidden"]),除非您希望选择器聚焦在浏览器默认隐藏的视觉和屏幕阅读器的元素
    【解决方案3】:
    $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])') 看看会发生什么。未禁用意味着您想要所有启用的元素。
    • 同样是关于不必添加:not([tabindex^="-"]的部分。证明:在您的控制台中尝试这一行:document.querySelectorAll('a, [tabindex]:not([tabindex="-1"]')[0] 它将选择一个节点,例如<a href="shouldnt-be-focused" tabindex="-1">nope</a> 对于它的价值,我认为这来自于这些选择器由“或”而不是“和”连接的误解,因此一旦遇到 标签,它就会满足选择器
    【解决方案4】:

    ally.js 可访问性库在此处提供了一个非官方的、基于测试的列表:

    https://allyjs.io/data-tables/focusable.html

    (注意:他们的页面没有说明执行测试的频率。)

    【讨论】:

      【解决方案5】:

      也许这个可以帮助:

      function focus(el){
      	el.focus();
      	return el==document.activeElement;
      }

      返回值:true = 成功,false = 失败

      参考: https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus

      【讨论】:

      • 它可以工作,但它失去了当前的焦点状态。 :)
      【解决方案6】:

      有一种更优雅的方式来处理这个问题:

      像下面的示例一样扩展元素原型。 然后你可以像这样使用它:

      element.isFocusable()
      

      *如果“元素”是可聚焦的,则返回 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>

      【讨论】:

      • 你介意是否也有类似“onfocus”的功能吗? - 任何被 UI 搞砸的功能很快就会让人失望。
      • 你要一个焦点事件监听器吗?像这样 -> developer.mozilla.org/en-US/docs/Web/API/Element/focus_event
      • 不,亲爱的,我告诉你,你的函数方式可能会出错,例如,如果元素中添加了焦点事件,它将在开发人员检查元素是否焦点时运行-能不能。
      • 亲爱的,这不是问题,您可以轻松添加事件保护器功能来聚焦和模糊,然后再将其删除。亲爱的,我在那里为你添加了它。
      • 更好但仍然是一个问题,如果元素有一个 passive EventListener 就像我们临时添加的那个,它将在 stopImmediatePropagation() 工作之前运行 - 也看起来像 Safari还不支持 preventScroll
      猜你喜欢
      • 2015-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2021-04-17
      • 1970-01-01
      相关资源
      最近更新 更多