单独的影子根中是否允许重复 ID?

kam*_*uel 14 html accessibility shadow-dom custom-element

tl;博士:

  1. 只要两个元素都在单独的影子根下,具有相同 ID 属性的两个元素是否有效?
  2. aria-labelledby在这种情况下,屏幕阅读器会正确处理吗?

例如,考虑这个自定义元素:

(function () {
  let template = document.createElement('template')
  template.innerHTML = `
    <svg viewBox="0 0 206 74"
         fill="none"
         xmlns="http://www.w3.org/2000/svg"
         role="img"
         aria-labelledby="logo-title">
      <title id="logo-title"><slot>Logo of Some Company.</slot></title>

      <path d="..." fill="..."/>
    </svg>
  `

  class Logo extends HTMLElement {
    constructor () {
      super()

      let shadowRoot = this.attachShadow({mode: 'open'})
      shadowRoot.appendChild(template.content.cloneNode(true))
    }
  }

  customElements.define('company-logo', Logo)
})()

Run Code Online (Sandbox Code Playgroud)

这样做是否有效:

<company-logo>
  Title One.
</company-logo>

<company-logo>
  Some other title.
</company-logo>
Run Code Online (Sandbox Code Playgroud)

这会是一个有效的 DOM,即使两者<title>共享相同的 ID?屏幕阅读器会为第一个徽标读“标题一”,为第二个徽标读“其他标题”吗?

Sup*_*arp 12

您可以在同一页面上拥有同一自定义元素的多个实例,因此内部 Shadow DOM 将通过设计共享相同的 ID。

就标准而言...

  • W3C 的 HTML5 Rec不包括 Shadow DOM,因此它不是他们的主题。

  • WHATWG 的 HTML Living Standard规定 ID 在节点树中应该是唯一的,但如果涉及扁平树(Light DOM 树和 Shadow DOM 树的组合),则该 ID 并不精确。据我了解,规格并没有说它无效:-)

在 HTML 元素上指定时,id 属性值在元素树中的所有 ID 中必须是唯一的,并且必须至少包含一个字符。

实际上,浏览器处理相同的 ID 不是问题。

我不认为 Aria Labels 可以跨越 Shadow DOM,它应该取决于浏览器的实现。这里的规范再次说明Shadow DOM。


2019年更新

正如 Google 在 Shadow DOM 的介绍中所述:

Scoped DOM 意味着您可以使用简单的 CSS 选择器、更通用的 id/class 名称,而不必担心命名冲突。

事实上,Shadow DOM 允许您创建可以分发和重用的 Web 组件,内部 ID 与同一页面中其他组件的其他 ID 匹配但由其他开发人员开发的可能性很高,Scoped DOM 是一个很好的答案。


2020 更新

请注意 Shadow DOM/ARIA 问题仍在讨论中

未来的AOM(可访问性对象模型)将允许编程方式解决此类问题

您不仅可以通过id标签链接元素,还可以通过引用链接元素:

element.ariaLabelledByElements = [ anotherElement, someOtherElement ]
Run Code Online (Sandbox Code Playgroud)

不需要处理 ID 的唯一性,也不需要处理 Shadow DOM 边界的可能性:-) 也许有一天:-(