发布时间:2024 年 11 月 6 日
从 Chrome 131 开始,您可以使用更多选项来设置 <details>
和 <summary>
元素的结构样式。现在,您可以在构建披露或手风琴微件时使用这些元素。
具体而言,Chrome 131 中引入的更改允许在这些元素上使用 display
属性,并添加了 ::details-content
伪元素来设置展开和收起部分的样式。
在 <details>
元素上设置 display
过去,无法更改 <details>
元素的显示类型。此限制现已放宽,例如,您可以在 <details>
元素上使用网格或 Flex 布局。
在以下示例中,排他性手风琴由并排放置的多个 <details>
元素组成。展开某个 <details>
元素时,其内容会放置在 <summary>
旁边。
演示
正在录制
这是通过对 <details>
元素使用以下 CSS 来实现:
details {
display: flex;
flex-direction: row;
}
还允许使用其他显示值,例如 grid
。
关于使用 display: inline
的注意事项
可能会产生意外结果的 display
值是 inline
。不是因为该功能无法正常运行,而是因为 HTML 解析器存在限制。
将 <details>
元素放置在段落中时,它会强制 HTML 解析器先关闭打开的段落,如 HTML 标准的第 13.2.6.4.7 节中所定义:
起始标记的标记名称为以下之一:“address”“article”“aside”“blockquote”“center”“details”“dialog”“dir”“div”“dl”“fieldset”“figcaption”“figure”“footer”“header”“hgroup”“main”“menu”“nav”“ol”“p”“search”“section”“summary”“ul”
如果打开的元素堆栈在按钮范围内包含 p 元素,则关闭 p 元素。 插入令牌的 HTML 元素。
因此,无论您是否设置了 display: inline
,<details>
都会沿块方向流动。
例如,以下标记
<p>Hello <details>…</details> world</p>
解析后变为:
<p>Hello </p><details>…</details> world<p></p>
您可以使用 Chrome 开发者工具检查已解析的标记,在此演示中自行查看。
请注意,这仅适用于将 <details>
嵌套在 <p>
中。在 <div>
内对 <details>
使用 display: inline
可以正常运行。
::details-content
伪
在浏览器中,<details>
元素是使用 Shadow DOM 实现的。它包含一个用于摘要的 <slot>
(具有默认摘要子项)和一个用于所有剩余内容的 <slot>
,这意味着 <details>
元素的所有子项(<summary>
元素除外)。
<details>
↳ #shadow-root (user-agent)
<slot id="details-summary">
<summary>Details</summary>
<!-- The summary goes here -->
</slot>
<slot id="details-content">
<!-- All content goes here -->
</slot>
</details>
除了在 <details>
上使用更多展示类型之外,现在还可以使用 ::details-content
伪元素定位内容 slot。您可以使用此伪类来设置封装 <details>
元素内容的容器的样式。
details::details-content {
border: 5px dashed hotpink;
}
如需仅在 <details>
元素处于打开状态时应用设置的样式,请在 <details>
选择器前面加上 [open]
选择器。
[open]::details-content {
border: 5px dashed hotpink;
}
建议仅当 <details>
元素处于 [open]
状态时,才对 ::details-content
伪元素应用样式。
演示
正在录制
::details-content
的 display
类型在 UA 样式表中设置为 block
,而之前是 display: contents
。在某些情况下,此项更改可能会对您不利,例如披露的内容依赖于 height: 100%
。如果您遇到此问题,可以按如下方式将 display
类型重新设置为 contents
来解决此问题:details[open]::details-content { display: contents; }
。
为 ::details-content
伪元素添加动画效果
您可以为 <details>
元素的内容添加动画效果,使其在展开时显示。在以下示例中,宽度从 0px
动画显示到 300px
。
::details-content {
transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
width: 0;
}
[open]::details-content {
width: 300px;
}
除了转换 width
之外,还需要转换 content-visibility
属性。这是因为它的值会在未打开状态和打开状态之间发生变化,如 User-Agent 样式表中定义的那样。由于该属性是可离散添加动画效果的属性,因此您需要使用 allow-discrete
关键字才能使其正常运行。
在之前分享的专属手风琴演示中添加了此功能后,结果如下所示:
演示
正在录制
height
也可以是动画。如需将动画效果设置为 height: auto
,您需要使用 interpolate-size
或 calc-size()
。此外,为防止内容溢出 ::details-content
伪元素,请向其应用 overflow: clip
。
::details-content {
transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
height: 0;
overflow: clip;
}
/* Browser supports interpolate-size */
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
[open]::details-content {
height: auto;
}
}
/* Fallback for browsers with no interpolate-size support */
@supports not (interpolate-size: allow-keywords) {
[open]::details-content {
height: 150px;
overflow-y: scroll; /* In case the contents should be taller than 150px */
}
}
您可以在以下演示中看到代码的实际效果,该演示灵感源自 Material UI 的手风琴。每个 <details>
元素的内容都会以流畅的动画效果呈现。
演示
正在录制
在不支持 ::details-content
的浏览器中,该组件仍可正常运行。访问者唯一看不到的是动画。
功能检测
如需检测 CSS 中是否支持 ::details-content
伪类,请使用以下代码段。
@supports selector(::details-content) {
…
}
您还可以使用此检测作为一种指示性检查,以确定访问者使用的浏览器是否支持额外的显示值。
无障碍注意事项
引入 ::details-content
伪元素和更改显示类型的能力不会影响 <details>
元素的可访问性。
与之前一样,至少在基于 Chromium 的浏览器中,并且根据 HTML 标准,<details>
元素是可搜索的,并且当浏览器尝试滚动到其隐藏内容以响应网页内查找、ScrollToTextFragment 和元素 fragment 导航时,该元素会自动展开。此设置不会更改。
不过,在使用排他性手风琴之前,请考虑它对用户是有帮助还是有害。虽然使用排他性手风琴可减少内容占用的视觉空间量,但用户可能需要打开许多项才能查看所有信息。这可能会让想要同时查看多件商品的买家感到沮丧。
如何设置标记的样式?
目前,列表标记的样式设置无法互操作,因为 Gecko 和(当前)Chromium 采用了一种方法,而 WebKit(之前与 Chromium 共享)采用了另一种方法。
该功能实现互操作后,我们的目标是让您更好地控制标记的样式。
更多演示
最后,我们再为您提供一些演示供您参考。它们都使用 ::details-content
。
UIKit 手风琴
演示
正在录制
此演示是根据 UIKit 手风琴构建的。此代码与之前分享的 Material UI 手风琴代码几乎相同。
部分打开的披露信息微件
演示
正在录制
此演示展示了一个部分打开的披露微件,其内容已显示在屏幕上。为此,content-visibility
始终设置为 visible
。由于涉及计算,height
会使用 calc-size()
进行动画处理。
::details-content {
content-visibility: visible; /* Make it always visible */
transition: height 0.5s ease;
height: 150px;
overflow: clip;
}
[open]::details-content {
height: calc-size(auto, size + 0.5rem); /* calc-size because we need to add a length */
}
为方便设置样式,内容封装在 wrapper div 中。wrapper div 会应用 padding
等布局样式,而 ::details-content
伪元素会进行动画处理。