在不远的过去,即使是基本的类似手风琴的交互也需要 JavaScript 事件监听器或 一些 CSS… 技巧。而且,根据所使用的解决方案,编辑底层 HTML 可能会变得很复杂。
现在,<details>
和 <summary>
元素(它们组合形成所谓的 “显示部件”)使得 创建和维护这些组件变得相对简单。
在我的工作中,我们使用它们来处理诸如常见问题之类的内容。

需要考虑几个问题
由于展开和折叠交互性已内置于 <details>
和 <summary>
HTML 标签中,因此您现在可以创建显示部件,而无需任何 JavaScript 或 CSS。但您可能仍然希望使用一些。如果未设置样式,<details>
显示部件会给我们带来两个问题。
<summary>
光标
问题 1:尽管 <summary>
部分邀请交互,但元素的默认光标是文本选择图标,而不是您可能期望的指向手势

<summary>
中嵌套的块级元素
问题 2:在 <summary>
元素内嵌套块级元素(例如标题)会将该内容推到箭头标记下方,而不是保持内联

CSS 重置修复
为了解决这些问题,我们可以在样式表的重置部分添加以下两个样式
details summary {
cursor: pointer;
}
details summary > * {
display: inline;
}
继续阅读以了解每个问题及其相应解决方案的更多信息。
<summary>
光标值
更改 当用户将鼠标悬停在页面上的元素上时,我们始终希望他们看到一个 “反映该元素上预期用户交互的光标。”
我们简要地提到了这样一个事实,尽管 <summary>
元素是交互式的(如链接或表单按钮),但其默认光标不是我们通常在这些元素中看到的指向手势。相反,我们得到 text
光标,这通常是我们期望在页面上输入或选择文本时看到的。
要解决此问题,请将光标的值切换为 pointer
details summary {
cursor: pointer;
}
一些著名的网站在为 <details>
元素设置样式时已包含此属性。 MDN Web 文档页面上的元素本身 正是这样做的。GitHub 也使用显示部件来处理某些项目,例如监视、加星和派生存储库的操作。

<summary>
元素上使用 cursor: pointer
。我猜想选择默认的 cursor: text
值是为了指示摘要文本(以及显示部件内容的其余部分)可以被用户选中。但是,在大多数情况下,我认为更重要的是表明 <summary>
元素是交互式的。
即使在我们已将光标值从 text
更改为 pointer
之后,摘要文本仍然可以选择。请注意,更改光标仅影响外观,而不影响其功能。
<summary>
内容显示为内联
将嵌套的 在前面共享的每个 FAQ 条目的 <summary>
部分内,我通常将问题括在 适当的标题标签 中(取决于页面大纲)
<details>
<summary>
<h3>Will my child's 504 Plan be implemented?</h3>
</summary>
<p>Yes. Similar to the Spring, case managers will reach out to students.</p>
</details>
在 <summary>
内嵌套标题可能出于以下几个原因:
- 一致的视觉样式。我喜欢我的 FAQ 问题看起来像页面上的其他标题。
- 使用标题可以使 Internet Explorer 和 Chromium 之前的 Edge 版本的用户保持页面结构有效,这些版本 不支持
<details>
元素。(在这些浏览器中,此类内容始终可见,而不是交互式。) - 正确的标题可以帮助辅助技术用户在页面内导航。(也就是说,
<summary>
元素中的标题构成了一个独特的案例,如下文详细解释。一些屏幕阅读器将这些标题解释为它们是什么,但其他一些则没有。)
标题与按钮
请记住,<summary>
元素有点奇怪。它在很多方面都像一个按钮。事实上,它甚至具有隐式 role=button
ARIA 映射。但是,与按钮非常不同, 标题允许直接嵌套在 <summary>
元素内。
这给我们(以及浏览器和辅助技术开发人员)带来了一个矛盾
- 允许在
<summary>
元素中使用标题以提供页面内导航帮助。 - 按钮会去除嵌套在其内的任何内容(如标题)的语义。
不幸的是, 辅助技术在处理这种情况方面不一致。一些屏幕阅读技术,如 NVDA 和 Apple 的 VoiceOver,确实承认 <summary>
元素内的标题。另一方面,JAWS 则不承认。
这对我们来说意味着,当我们将标题放在 <summary>
内时,可以设置标题的外观样式。**但我们无法保证标题实际上会被解释为标题!**
换句话说,在那里放一个标题可能不会造成伤害。只是它可能并不总是起作用。
将所有内容设为内联
当在我们的 <summary>
内直接使用标题标签(或其他块级元素)时,我们可能希望将其 display
样式更改为 inline
。否则,我们将得到一些不希望的换行,例如展开/折叠箭头图标显示在标题上方,而不是旁边。
我们可以使用以下 CSS 将 display
值应用于每个标题(以及直接嵌套在 <summary>
中的任何其他元素)
details summary > * {
display: inline;
}
关于此技术的几个说明。首先,我建议使用 inline
,而不是 inline-block
,因为当标题文本扩展到一行以上时,inline-block
仍然会出现换行问题。
其次,您可能很想替换 <summary>
元素的默认 display: list-item
值为 display: flex
,而不是更改嵌套元素的 display
值。至少我是这样想的!但是,如果我们这样做,箭头标记将消失。哎呀!
额外提示:排除 Internet Explorer 的样式
我之前提到过,Internet Explorer 和 Chromium 之前的 Edge 版本(也称为 EdgeHTML)不支持<details>
元素。因此,除非我们为这些浏览器使用 polyfill,否则我们可能需要确保我们的自定义展开部件样式不会应用于它们。否则,最终会出现所有内联样式都会使元素混乱的情况。

<summary>
标题在 Internet Explorer 和 EdgeHTML 中可能会产生奇怪或不希望有的效果。此外,当发生这种情况时,<summary>
元素不再具有交互性,这意味着光标的默认text
样式比pointer
更合适。
如果我们决定希望重置样式仅针对合适的浏览器,我们可以添加一个功能查询,以防止 IE 和 EdgeHTML 始终应用我们的样式。以下是如何使用@supports
检测仅这些浏览器支持的功能来实现此目的
@supports not (-ms-ime-align: auto) {
details summary {
cursor: pointer;
}
details summary > * {
display: inline;
}
/* Plus any other <details>/<summary> styles you want IE to ignore.
}
IE 实际上根本不支持功能查询,因此它将忽略上述块中的所有内容,这很好!EdgeHTML确实支持功能查询,但它也不会应用块中的任何内容,因为它是唯一支持-ms-ime-align
的浏览器引擎。
这里的主要注意事项是,Chrome(即 12-27 版本)和 Safari(macOS 和 iOS 6-8 版本)的一些较旧版本也支持<details>
,但不支持功能查询。使用功能查询意味着这些浏览器(截至 2021 年 1 月,占全球使用量的约 0.06%)也不会应用我们的自定义展开部件样式。
使用@supports selector(details)
块,而不是@supports not (-ms-ime-align: auto)
,将是一个理想的解决方案。但选择器查询比基于属性的功能查询的浏览器支持更少。
最终思考
一旦我们设置了 HTML 结构并添加了两个 CSS 重置样式,我们就可以根据需要美化所有展开部件。即使是一些简单的边框和背景颜色样式也可以极大地提升美观性和可用性。只需知道自定义<summary>
标记可能会有点复杂!
嘿,那个 CSS 功能查询非常棒!但我想知道如何正确地为这些内容设置动画,因为设置过渡不起作用。您能否推荐一些好的动画,以便这些动画不会那么突兀?
可以尝试修改这个,我在@keyframes中使用了
transform: scaleY(0);
https://dev.to/pixmy/animate-details-tag-with-pure-css-52j7#:~:text=The%20tag%20can%20be,the%20open%20attribute%20is%20set.%22
我更喜欢微妙的动画,所以我一直在使用
是的!非常感谢你,Greg - 我真的很感激。请继续做很棒的事情。
:)
我不确定说“在那里放一个标题可能不会造成伤害。它可能并不总是起作用。”是否准确。我认为问题比这更严重。JAWS 不仅不会在展开内容中宣布标题,而且也不会将其包含在标题列表中,而屏幕阅读器用户通常会使用标题列表来导航页面。对我来说,每当在展开部件中需要标题时,这都是一个障碍。在这些情况下,我使用 javascript 而不是 details-summary。
有人可以帮我理解为什么我需要将(而不是)的子元素包装在块元素中才能使用 flexbox 进行布局吗?
带有 Codepen 的最小示例:https://codepen.io/jbrains/pen/OJbmzoB
非常感谢。
很棒的文章,但我对你的选择器用法有一个疑问。编写像
details summary
这样的选择器是否不必要地具体且冗余?<summary>
唯一允许的父元素是<details>
,所以我真的不明白为什么你需要包含它。最佳实践是使选择器的特异性得分尽可能低,并且尽可能短,所以你不应该只使用summary
作为选择器吗?使用后代组合器选择器而不是类型选择器是否有我遗漏的原因?
我想使用默认的箭头标记,并且希望摘要文本与箭头标记的颜色不同。
这可能吗?
当然可以。您可以通过
::marker
伪元素来设置摘要的箭头样式。一些小的意见。
不要在 summary 标签中放置标题,这对某些屏幕阅读器来说是不利的,因为它们会忽略它们,导致标题不在页面的正确流程中。
此外,不要为此使用 cursor pointer,这不是链接。“交互式项目”不需要 cursor pointer。没有人会错过它。但是,如果文本光标会让你感到烦恼,你可以添加一个普通鼠标箭头作为光标。
我强烈不同意更改光标。Pointer 用于链接;在超出此范围的很多地方使用它们会产生误导。在表单中,您不会通过让用户误以为标签是链接或通过在文本输入框中没有垂直线来混淆他们。
对于 summary 元素,光标应该指示文本的可选择性 - 就像大多数其他文本内容一样。与按钮一样,不要使用 pointer,而是使用背景颜色。
正如 Dave Rupert 所写,避免在 summary 中使用 h* 标签
https://daverupert.com/2019/12/why-details-is-not-an-accordion/