发布时间:2024 年 11 月 6 日
从 Chrome 131 开始,您可以使用更多选项来设置 <details>
和 <summary>
元素的结构样式。现在,您可以在构建展开式或折叠式 widget 时使用这些元素。
具体而言,Chrome 131 中引入的更改使您能够对这些元素使用 display
属性,并添加了 ::details-content
伪元素来设置可展开和收起的部分的样式。
浏览器支持
在 <details>
元素上设置 display
过去,无法更改 <details>
元素的显示类型。现在,此限制已放宽,例如,您可以在 <details>
元素上使用网格或 Flex 布局。
在以下示例中,排他式折叠菜单由几个并排放置的 <details>
元素组成。展开其中一个 <details>
元素后,其内容会放置在 <summary>
旁边。
演示
正在录制
为此,您可以使用以下 CSS 在 <details>
元素上使用 Flex 布局:
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 开发者工具检查已解析的标记,在此演示中亲自验证。
请注意,这仅适用于在 <p>
中嵌套 <details>
。对 <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
伪元素定位内容槽。您可以使用此伪元素为封装 <details>
元素内容的容器设置样式。
details::details-content {
border: 5px dashed hotpink;
}
如需仅在 <details>
元素处于打开状态时应用设定的样式,请在其前面附加 [open]
选择器。
[open]::details-content {
border: 5px dashed hotpink;
}
建议仅在 <details>
元素处于 [open]
状态时,对 ::details-content
伪元素应用样式。
演示
正在录制
UA 样式表中 ::details-content
的 display
类型已设为 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 */
}
为方便设置样式,内容封装在封装容器 div 中。封装容器 div 会应用布局样式(例如 padding
),并且 ::details-content
伪元素会进行动画处理。