HTML 样式 使用现代 CSS
HTML 元素(统称为披露小部件)不易设置样式。由于存在限制,人们经常使用自定义组件制作自己的版本。但是,随着 CSS 的发展,这些元素变得更容易自定义。在本文中,我将介绍如何自定义披露小部件的外观和行为。
如何 一起工作?
`
当用户点击该小部件或将焦点放在该小部件上并按下空格键时,它会打开并显示其他信息。三角形标记指向下方,表示它处于打开状态:


披露小部件有一个始终显示的标签,由` ` 元素。这是第一个子元素。如果省略,浏览器会提供默认标签。通常,它会显示“详细信息”:

您还可以在 ` ` 元素来表示附加信息:
Do you want to know more?
Additional info
The average human head weighs around 10 to 11 pounds (approximately 4.5 to 5 kg).
造型
在设计` ` 元素。在讨论一些常见用例之前,让我们先介绍一下基础知识。
` ` 元素类似于 `[ ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)` 元素,因为其默认样式包含 `display: list-item`。因此,它支持 `[list-style](https://developer.mozilla.org/docs/Web/CSS/list-style)` 简写属性及其全写属性。浏览器对 list-style 属性的支持相当好,但 Safari 仍然落后。
公开小部件具有两个伪元素来设置其组成部分的样式:

在以下部分中,我将演示一些较新的、鲜为人知的自定义披露小部件的方法。
动画打开和关闭动作
当您打开披露小部件时,它会立即打开。眨眼间,您就会错过它!
最好以更渐进的方式从一种状态过渡到另一种状态,以向用户展示其操作的影响。我们可以为公开小部件的打开和关闭操作添加过渡动画吗?简而言之,可以!
为了实现动画效果,我们希望隐藏内容的高度从零过渡到最终高度。`height` 属性的默认值为 `auto`,这让浏览器根据内容计算高度。在添加 `[interpolate-size](https://nerdy.dev/interpolate-size)` 属性之前,在 CSS 中无法将动画设置为 `auto` 值。虽然浏览器对我们需要使用的较新的 CSS 功能(主要是 `interpolate-size` 和 `::details-content`)的支持有点有限,但这是渐进式增强的一个很好的例子。它目前可以在 Chrome 中使用!
这是动画的 CodePen 示例。
披露动画如何运作?
首先,我们添加“interpolate-size”,以便我们可以过渡到“auto”高度:
details { interpolate-size: allow-keywords; }
接下来,我们要描述封闭样式。我们希望“附加信息”内容的高度为零,并确保没有内容可见,即,我们希望防止溢出。
我们使用 `::details-content` 伪元素来定位隐藏内容。我使用 `block-size` 属性而不是 `height`,因为使用逻辑属性是一个好习惯。我们需要在过渡中包含 `content-visibility`,因为浏览器在内容处于关闭状态时会在其上设置 `content-visibility: hidden` — 如果不包含它,关闭动画将不起作用:
/* closed state */ details::details-content { block-size: 0; transition: content-visibility, block-size; transition-duration: 750ms; transition-behavior: allow-discrete; overflow: hidden; }
动画仍然无法按预期工作,因为 `content-visibility` 属性是一个离散动画属性。这意味着没有插值;浏览器将在两个值之间切换,以便在整个动画持续时间内显示过渡内容。我们不希望出现这种情况。
如果我们包含“transition-behavior:allow-discrete;”,则值会在动画的最后翻转,因此我们得到了逐渐的过渡。
此外,当披露小部件处于中间状态时,我们将“block-size”设置为“0”,从而导致内容溢出。我们在打开时显示大部分内容。为了防止这种情况发生,我们添加了“overflow: hidden”。
最后,我们添加打开状态的样式。我们希望最终状态的大小为“自动”:
/* open state */ details[open]::details-content { block-size: auto; }
以上就是大致内容。如果您想要更详细的视频解释,请查看 Kevin Powell 的演示,了解如何制作动画 ` `。
为披露小部件制作动画时还有其他注意事项吗?
如果“附加信息”内容比` ` 内容。这可能会导致不必要的布局偏移。在这种情况下,您可能需要在 `
与任何动画一样,您应该考虑对动作敏感的用户。您可以使用以下方法来满足这种情况:
>@media (prefers-reduced-motion) { /* styles to apply if a user's device settings are set to reduced motion */ details::details-content { transition-duration: 0.8s; /* slower speed */ } }
实施独家
一种常见的 UI 模式是手风琴组件。它由一堆可展开以显示其内容的披露小部件组成。要实现此模式,您只需要多个连续的`
Payment Options
...
Personalise your PIN
...
How can I add an additional cardholder to my Platinum Mastercard
...
默认样式相当简单:

每个`
此模式的一个变体是使手风琴独占,以便一次只能打开其中一个披露小部件。一旦打开一个,浏览器就会关闭另一个。您可以通过``的``name``属性创建独占组
Payment Options
...
Personalise your PIN
...
How can I add an additional cardholder to my Platinum Mastercard
...
在使用专属折叠面板之前,请考虑它是否对用户有帮助。如果用户可能想要获取更多信息,这将要求他们经常打开项目,这可能会令人沮丧。
此功能目前在所有现代浏览器上均受支持,因此您可以立即使用它。
设置摘要标记的样式
披露小部件旁边通常会显示一个小三角形标记。在本节中,我们将介绍设计此标记的样式的过程。
标记与` ` 元素。`[::marker](https://developer.mozilla.org/docs/Web/CSS/::marker)` 伪元素的添加意味着我们可以直接设置标记框的样式。但是,我们只能使用一小部分 CSS 属性:
正如前面提到的,` ` 类似于 `[ ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)`;它支持简写属性及其全写属性。虽然这听起来可能有点杂乱,但通过一些示例将更容易理解样式选项。
在开始举例之前,先简单介绍一下浏览器支持情况。在撰写本文时,Safari 是唯一一款不完全支持标记样式的主流浏览器:
更改标记的颜色和大小
假设我们想将三角形标记的颜色改为红色,并将其放大 50%。我们可以执行以下操作:
summary::marker { color: red; font-size: 1.5rem; }

这应该适用于所有浏览器。这是 CodePen 示例。
调整标记的间距
默认情况下,标记位于文本内容的侧面` ' 并且它们在同一个边界框中。`list-style-position` 设置为 `inside`。当它处于打开状态时,“附加信息”直接位于标记下方。也许你想改变这个的间距和对齐方式:

如果我们将“list-style-position”设置为“outside”,则标记位于“ ` 边界框。这使我们能够调整摘要文本和标记之间的空间:
summary { list-style-position: outside; padding-inline-start: 1rem; }
您可以在上面的屏幕截图中的第二个实例中看到这一点。
以下是该示例的 CodePen:
更改标记文本/图像
如果要更改标记的内容,可以使用 `::marker` 伪元素的 `content` 属性。根据您的偏好,您可以将其设置为 `text`。在我的示例中,我使用拉链嘴表情符号表示闭合状态,使用张嘴表情符号表示打开状态:
summary::marker { content: '🤐 '; font-size: 1.2rem; } details[open] summary::marker { content: '😮 '; }
要使用图像作为标记,可以使用 `::marker` 伪元素的 `content` 属性,或者 ` `:
summary::marker { content: url("arrow-circle-right.svg"); /* you can use a data URI too */ content: url('data:image/svg+xml,'); } /* OR */ summary { list-style-image: url("arrow-circle-right.svg"); }
在以下示例中,我们使用 Material Symbols 中的两个箭头图标作为标记。向右的箭头表示关闭状态,向下的箭头表示打开状态:
这些示例在 Chrome 和 Firefox 中将按预期运行,但 Safari 将忽略样式。您可以将其作为渐进式增强来处理,然后就此结束。但如果您希望在所有浏览器中具有相同的外观,您可以隐藏标记,然后添加自己的图像作为替代。这为您提供了更多的自由:
/* Removes default marker. Please consider accessibility, read below. */ summary::-webkit-details-marker { display: none; } summary { list-style: none; }
您可以使用新的标记图标(例如内联图像或通过伪元素)直观地指示状态。` ` 已经(大部分)指示了展开/折叠状态。因此,如果您使用内联图形,则应将其视为装饰性的。空的 `alt` 属性会执行以下操作:
Do you want to know more?
Yes
您可以选择将标记定位在` 如果你愿意的话:
Do you want to know more?
Yes
但是,需要注意的是,隐藏标记会导致屏幕阅读器出现可访问性问题。如果删除标记,Firefox、VoiceOver、JAWS 和 NVDA 都存在一致宣布披露小部件切换状态的问题。不幸的是,样式与状态相关。最好避免这样做。
为“附加信息”部分添加样式
您可能希望对披露小部件的“附加信息”部分进行样式设置,而不会将样式泄露给` `。因为你可以在 ` 中拥有可变数量的元素
Do you want to know more about styling the hidden section?
Styling hidden section
Tell me more.
This is a div
我的做法是排除“ ` 元素使用 `:not()` 函数。请记住,这将针对每个元素,而不是将内容作为单个部分!
details > *:not(summary) { color: palegoldenrod; font-size: 0.8em; margin-block-start: 1rem; }

或者,您可以使用 `::details-content` 伪元素,该元素针对整个部分。这就是为什么您要使用它来为打开和关闭状态转换制作动画的原因:
/* browser support is limited */ details::details-content { color: palegoldenrod; font-size: 0.8em; margin-block-start: 1rem; }

注意到区别了吗?本节开头只有一个边距。` `和` ` 没有边距。使用 `::details-content` 伪元素的缺点是浏览器支持目前仅限于 Chrome。 设计披露小部件时的常见错误 从历史上看,无法更改 更改显示类型时要小心 。默认值为 display: list-item;;如果将其更改为 display: block;,则可能会导致标记在某些浏览器中被隐藏。这是 Firefox 中的一个问题: 你不能嵌套 因为 元素具有按钮的默认 ARIA 角色,它会从子元素中删除所有角色。因此,如果你想要一个像 在一个 ,屏幕阅读器等辅助技术将无法将其识别为标题。请尽量避免这种模式: 剧透 隐藏标记会导致某些屏幕阅读器出现可访问性问题。如果删除标记,Firefox、VoiceOver、JAWS 和 NVDA 都无法持续播报披露小部件的切换状态 未来还会有更多变化吗? 最近有一项重大提议旨在帮助实现“ 删除 CSS 显示属性限制,以便您可以使用其他显示类型,如 flex 和 grid 更清晰地指定影子树的结构。这将有助于与 Flexbox 和 CSS Grid 实现互操作性 添加 ::details-content 伪元素来处理第二个插槽,以便为“附加信息”添加一个容器 令人兴奋的消息是,上述列表中的第 1 项和第 3 项已在 Chrome 131 中发布(截至 2024 年 11 月)。下一阶段应该是着手改进标记的样式。此外,还有一组相关更改将有助于提高为这些元素制作动画的能力。 结论 ` '阿喀琉斯之踵' 你的前端是否占用了用户的 CPU? 随着 Web 前端变得越来越复杂,资源占用大的功能对浏览器的要求也越来越高。如果您有兴趣监控和跟踪生产环境中所有用户的客户端 CPU 使用率、内存使用率等,请尝试 LogRocket。 LogRocket 就像是 Web 和移动应用的 DVR,记录 Web 应用、移动应用或网站上发生的所有事情。您无需猜测问题发生的原因,而是可以汇总和报告关键的前端性能指标、重播用户会话以及应用程序状态、记录网络请求并自动显示所有错误。 实现 Web 和移动应用程序调试方式的现代化 — 开始免费监控。