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

tl;dr:

  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)
})()

这样做是否有效:

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

<company-logo>
  Some other title.
</company-logo>

这是否是有效的DOM,即使这两个<title>共享相同的ID?屏幕阅读器是否会为第一个徽标读取"Title One",为第二个徽标读取"其他标题"?


解决方案

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

就标准而言.

  • W3C's HTML5 Rec不包括卷影DOM,因此不是他们的主题。

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

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

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

我不认为Aria标签可以跨越Shadow DOM,它应该取决于浏览器的实现。此处再次the specs says nothing位于阴影DOM上。


2019更新

如Google简介中所述,sur Shadow DOM:

作用域DOM意味着您可以使用简单的CSS选择器、更通用的ID/类名,而不必担心命名冲突。

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


2020更新

注意:影子DOM/ARIA问题仍然being discussed。

将来的AOM(辅助功能对象模型)将以编程方式允许to solve this kind of question。

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

element.ariaLabelledByElements = [ anotherElement, someOtherElement ]

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

相关文章