自主自定义元素中是否可以有一个“<li>”,而父元素“<ul>”不在同一个 ShadowDOM 中?

问题描述 投票:0回答:1

我过去的理解是,列表项

<li>
标签必须是
<ul>
<ol>
<menu>
标签的直接子代。

但我最近一直在使用 Web 组件和自主自定义元素。我读到,对于自主自定义元素,内容模型是透明的。请参阅https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-core-concepts

我想要一个自主自定义元素

<my-list>
,其 ShadowDOM 中有一个
<ul>
(或其他有效父元素之一,例如
ol
menu
),以及第二个自主自定义元素
<my-list-item>
ShadowDOM 中有一个
<li>
。 (参见下面的“示例”。)

为什么?几个原因:

  • CSS 样式范围仅限于 ShadowDOM
  • 额外的事件处理程序
  • 某些用例可能会发生更多情况,例如每个
    <li>
    除了
    <slot>
  • 之外还包含 ShadowDOM 子级
  • 我使用的是 Lit 3,所以很自然地编写一个 Web 组件

根据 HTML 5 规范和辅助功能指南,类似下面这个示例的内容是有效还是无效?

注意:我使用

<template shadowrootmode="open">
(参见此处 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template#shadowrootmode )使我的示例更加独立。在我的实际代码中,我使用 Lit 框架,它以编程方式创建 ShadowDOM。

示例:

<my-list role="presentation">
  <template shadowrootmode="open">
    <ul>
      <slot />
    </ul>
  </template>

  <my-list-item role="presentation">
    <template shadowrootmode="open">
      <li>
        <slot />
      </li>
    </template>

    My text here
  </my-list-item>
</my-list>

我认为这可能有效的另一个原因是我看到 axe-core 有一个看起来相似的单元测试:

https://github.com/dequelabs/axe-core/blob/develop/test/checks/lists/only-listitems.js#L224-L232

    it('should return false in a shadow DOM pass', () => {
      const node = document.createElement('div');
      node.innerHTML = '<li>My list item </li>';
      const shadow = node.attachShadow({ mode: 'open' });
      shadow.innerHTML = '<ul><slot></slot></ul>';

      const checkArgs = checkSetup(node, 'ul');
      assert.isFalse(checkEvaluate.apply(checkContext, checkArgs));
    });

但看起来这是 axe-core 中的特定模式/选项,而不是默认行为?

accessibility web-component
1个回答
0
投票

理论上,你所说的都是有道理的。这意味着以下事情是正确的:

  • 自定义元素具有符合规范的透明内容模型。
  • 根据规范,当透明元素相互嵌套时,必须迭代应用该过程。

因此,这意味着您应该被允许创建完全自定义的列表。所以,这应该有效:

<script>
  class MyList extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({mode: 'open'});
      this.shadowRoot.innerHTML = `
        <ul aria-label="Custom List">
          <slot></slot>
        </ul>
      `;
    }
  }

  class MyListItem extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({mode: 'open'});
      this.shadowRoot.innerHTML = `
        <li>
          <slot></slot>
        </li>
      `;
    }
  }

  customElements.define('my-list', MyList);
  customElements.define('my-list-item', MyListItem);
</script>

<my-list aria-label="Custom Wrapper">
  <my-list-item>Item 1</my-list-item>
  <my-list-item>Item 2</my-list-item>
</my-list>

在这种情况下,

<ul>
的影子根与
<li>
元素的影子根不同。对于上述定义,浏览器最终会生成以下可访问性树(来自 Chrome 浏览器):

因此,根据规范,浏览器正确生成了大多数工具应该看到的可访问性树。我最好的猜测是,

axe-core
在此给定测试中依赖相同的规格。但在实践中,情况有所不同。

  • 许多辅助工具都有自定义解析器,这会破坏和/或对 HTML 结构做出假设(ShadowRoot 是一个常见的障碍)
  • 甚至W3C 验证器也无法识别自定义元素。
  • 尽管自定义元素规范正式考虑具有透明内容模型的自定义元素,但
    <ul>
    <ol>
    的规范仍然明确限制它们仅具有
    <li>
    <script>
    <template>
    。 (将来应该解决这个问题)。

因此,根据规范,您最好在完全不同的 Shadow DOM 中的自定义列表中拥有自定义列表元素,但实际上,可访问性仍然会受到影响。如果可能,最好依赖经典的

ul > li
ol > li
层次结构。

© www.soinside.com 2019 - 2024. All rights reserved.