关于 `details` 的更多细节

Avatar of Geoff Graham
Geoff Graham

DigitalOcean 为您的旅程各个阶段提供云产品。立即开始使用 $200 免费积分!

最近关于旧的 <details><summary> 元素有很多讨论!我看到 Lea Verou 最近发布了一条关于该元素 display 行为的推文,这引发了更多人的观察和使用说明,包括关于 <summary> 是否应该允许包含交互式元素的 重新燃起的讨论

有很多点需要连接起来,我会尽力做到这一点。

我们可以更改嵌套在 <details> 元素中的元素的显示吗?

超级奇怪!如果我们打开 DevTools,用户代理样式表告诉我们 <details> 显示为块级元素。

注意所需的 <summary> 元素以及其中的两个额外的 <div>。我们可以覆盖 display,对吧?

我们可能期望的是 <details> 现在具有 40vh 的显式高度,并且有三行,其中第三行占用前两行剩余的空间。就像这样

Open details element with a summary of foo and two child elements, one yellow and one blue. The blue element takes up the rest of the space left by summary and the first child.

哎呀,但第三行不... 不... 那样做。

Open details element with a summary of foo and two child elements, one yellow and one blue. The summary and two child elements are all the same height.

显然,我们正在处理的是一个无法将网格行为应用于其网格项的网格容器。但 HTML 规范告诉我们

details 元素预期呈现为一个 块级框。该元素还预期在内部有一个 影子树,其中包含两个 槽位

(强调我的)

稍后一点

details 元素的第二个 槽位 预期当 details 元素没有 open 属性时,其 style 属性设置为 “display: block; content-visibility: hidden;”。当它具有 open 属性时,style 属性预期将从第二个 槽位 中移除。

(再次强调我的)

所以,规范说第二个槽位——示例中的两个额外的 <div>——仅在 <details> 关闭时被强制为块级元素。当它打开时——<details open>——它们应该符合覆盖用户代理样式的网格显示... 对吧?

这就是争论。我理解 槽位 默认情况下设置为 display: contents,但是将嵌套的元素塞入槽位并删除对它们进行样式的能力似乎不对劲。是规范问题,内容是槽位,还是浏览器问题,我们无法覆盖它们的 display,即使它们在框树中?更聪明的人可以启发我,但这似乎是一个不正确的实现。

<details> 是容器还是交互式元素?

很多人都 使用 <details> 来切换菜单 打开和关闭。这是一个由 GitHub 推广的实践

DevTools open with the details element highlighted in orange.

似乎很合理。规范肯定允许这样做

details 元素 表示 一个公开窗口,用户可以从中获取更多信息或控制

(强调我的)

好吧,所以我们可能期望 <details> 是容器(它有一个 隐式 role=group),而 <summary> 是一个交互式元素,它设置容器的 open 状态。这很有道理,因为 <summary> 在某些上下文中有一个隐式的 button 角色(但没有相应的 WAI-ARIA 角色)。

Melanie Sumner 做了一些调查,这不仅似乎与之相矛盾,而且得出结论,使用 <details> 作为菜单可能不是最好的选择。看看当 <details> 在没有 <summary> 元素的情况下呈现时会发生什么

它完全按照规范在缺少 <summary> 时建议的那样做——它创建了自己的

元素的第一个 summary 元素子级(如果有的话) 表示 详细信息的摘要或说明。如果没有子级 summary 元素,用户代理应提供自己的说明(例如,“Details”)。

(强调我的)
DevTools open with the summary markup highlighted in orange.

Melanie 通过 HTML 验证器运行了它,结果——令人惊讶!——它无效

Error, element details is missing a required instance of child element summary.

所以,<details> 需要 <summary>。当 <summary> 丢失时,<details> 会创建自己的,尽管它被中继为无效标记。当 <summary> 存在时,一切都很好,并且有效

Success message from the W3C HTML validator with the markup for a details element and summary that contains a link element.

所有这些都引发了一个新的问题:为什么 <summary> 被赋予了一个隐式的 button 角色,而 <details> 似乎是交互式元素?也许这是另一个浏览器实现不正确的案例?再说一次,规范确实将两者都归类为 交互式元素。你可以看到所有这些是如何变得非常令人困惑的。

无论哪种方式,Melanie 最终得出结论,我们应该避免将 <details> 用于菜单,这是基于辅助技术如何读取和宣布包含交互式元素的 <details>。该元素被宣布,但在你(嗯, <details> 交互)之前,除了它之外没有提到任何交互式控件。只有这样,像链接列表这样的东西才会被宣布。

此外,折叠的 <details> 内部的内容被排除在页面内搜索之外(除了 Chromium 浏览器,它可以在撰写本文时访问折叠的内容),这使得搜索变得更加困难。

<summary> 应该允许交互式元素吗?

这是 此开放线程 中提出的问题。想法是这样的东西将是无效的

<details>
  <summary><a href="...">Link element</a></summary>
</details>

<!-- or -->

<details>
  <summary><input></summary>
</details>

Scott O’Hara很好地总结了 为什么这是一个问题

当使用虚拟光标导航时,JAWS 完全无法发现该链接。如果通过 Tab 键导航到摘要元素,JAWS 会宣布“示例文本,按钮”作为元素的名称和角色。如果再次按下 Tab 键,JAWS 仍然会宣布“示例文本,按钮”,即使键盘焦点位于链接上。

[…]

关于不同 AT 如何处理摘要内容模型的各种问题,我可以继续谈下去… 但那只会让这条评论超过必要的长度。总之,摘要内容模型为使用 AT 的人带来了非常不一致且有时完全失效的体验。

Scott 在 ChromiumWebKit 中打开了票证以纠正此行为。感谢,Scott!

然而,它是有效的 HTML

Success message from the W3C validator with details markup.

Scott 在一篇 单独的博客文章 中进一步说明。例如,他解释了为什么在 <summary> 上添加 role=button 似乎是一个合理的解决方案,以确保它被辅助技术始终宣布。这也将解决关于 <summary> 是否应该允许交互式元素的争论,因为 按钮不能包含交互式元素。唯一的问题是 Safari 然后将 <summary> 视为一个标准按钮,它失去了 expandedcollapsed 状态。所以,正确的角色被宣布了,但现在它的状态却没有。🙃

我们现在去哪里?

你是否害怕在存在所有这些问题和不一致的情况下使用 <details>/<summary>?我当然害怕,但只是为了确保它里面的内容为用户提供了正确类型的体验和预期。

我很高兴这些对话正在进行,而且是在公开进行的。正因为如此,您可以对 Scott 提出的关于如何定义<summary> 内容模型的三个解决方案发表评论,为他提出的问题投票,并在您操作时报告您自己的问题和用例。希望我们对这些元素的使用方式和预期功能了解得越多,它们就能更好地实现。