本文中,我们将探讨几种简单的方法来美化HTML中的<details>
元素,这是一个在网页上展示和隐藏内容的非常有用的元素。
在HTML中拥有一个无需JavaScript即可使用的简单披露元素非常方便,但<details>
元素的默认样式可能对某些人来说不够吸引。幸运的是,改变这个元素的样式相当简单。
下面的目录就是一个使用<details>
元素的例子。我们为其添加了一个简单的边框和一些内边距。
Table of Contents
介绍详情元素
以下是<details>
元素的基本代码:
<details>
<summary>Click me!</summary>
<p>Peekaboo! Here's some hidden content!</p>
</details>
基本上,任何HTML内容都可以放置在<details>
元素内部。<summary>
元素提供了一个提示,用户可以点击该元素以显示更多内容,并且它必须是<details>
元素的第一个子元素。
这里是一个此代码的实时示例:
Click me!
躲猫猫!这里有一些隐藏的内容!
让我们看看所有可以使用CSS来增强<details>
元素外观的方法。
背景颜色、边框和内边距
A really simple way to enhance the look of the <details>
element is to add some padding along with a border or some background colors.
添加边框
如上面的目录所示,一个简单的边框可以大大增强和定义<details>
元素,再加上一些内边距和一个轻微的边框半径:
details {
padding: 10px;
border: 5px solid #f7f7f7;
border-radius: 3px;
}
这就是我们上面用来样式化目录的简单代码。
添加一些背景颜色
让我们为<details>
元素添加一个背景颜色,而不是边框:
details {
padding: 10px;
background-color: #e4eaef;
border-radius: 5px;
}
结果显示在下面的Pen中。
背景颜色使元素更加明显,内边距有助于在其中创建一些空间。
我们还可以为<summary>
元素赋予一个不同的背景颜色,以将其与剩余内容区分开来,并改变其文本颜色。
summary {
background-color: #2196F3;
color: white;
padding: 10px;
}
请注意,更改<summary>
元素的文本颜色也会改变标记箭头的颜色。这是因为标记实际上是附加到<summary>
元素上的,就像项目符号等标记附加到列表项上一样。我们将在下面看到如何分别对它们进行样式设置。
标记样式设置
<summary>
元素的display
属性被设置为list-item
。因此,它默认带有的箭头(▶)可以像HTML列表项的默认标记一样被修改。我们可以改变使用的字符,并独立改变其颜色。
改变标记颜色
让我们将默认标记设置为不同的颜色。为了好玩,我们还可以增加标记的字体大小。这可以通过::marker
伪元素来实现:
summary::marker {
color: #e162bf;
font-size: 1.2em;
}
结果如下所示。
这是一个简单而优雅的解决方案,尽管遗憾的是::marker
在Safari中不受支持,如果这是一个关键问题,请参见下面的其他选项。
改变标记间距
默认情况下,标记箭头与摘要文本非常接近。它的list-style-position
属性被设置为inside
。如果我们将其更改为outside
,我们可以通过添加一些左侧填充来在摘要文本和标记之间添加空间。我们还需要添加一些左侧边距,以使三角形不会悬挂在容器外部:
summary {
list-style-position: outside;
margin-left: 30px;
padding: 10px 10px 10px 20px;
border-radius: 5px;
}
结果如下所示。
I’ve exaggerated the spacing between the arrow marker and the summary text just to make it obvious. Unfortunately, using list-style-position: outside;
with the <summary>
element doesn’t work in Safari. Fortunately, there are other options, as we’ll see below.
改变标记形状
我们<summary>
元素上的标记不一定是三角形。我们可以随心所欲地替换它:
summary {
list-style-type: '⬇ ';
}
注意,我们使用了'⬇ '
(箭头旁边有一个空格),这是上述尝试的间距的替代方案。
现在我们用一个向下的箭头代替了三角形。但是……当<details>
元素打开时,那个向下的箭头不会改变。这是因为<details>
元素有两种状态——closed
和open
——我们只为closed
状态设置了标记样式。所以让我们也为open
状态设置一个标记:
details[open] > summary {
list-style-type: '⬆ ';
}
这次,我们使用了一个向上的箭头。这为我们带来了如下所示的结果。
该死!Safari再次让我们失望,因为它也不支持<summary>
元素上的list-style-type
。不过别灰心,我们将在下面探讨更复杂的解决方案。
我们可以尝试各种其他字符,如+和-,✓和Χ或✗,⋁和⋀,甚至可以用★或其他有趣的符号如🍏 🍌 🍓 🍋和🍐来玩,但要记住,这些字符可能在所有系统上都不起作用,所以要小心一些,而且再次提醒,list-style-type
在Safari中肯定无效。
为summary元素创建自定义标记
如上所述,尽管我们可以能够为默认标记设置不同的字符,并赋予其颜色和字体大小等样式,但这样做可能会遇到问题。更好的选择可能是完全移除标记,并创建一个完全自定义的替代方案。
移除自定义标记
与列表项标记一样,我们可以完全移除标记:
summary {
list-style: none;
}
/* 唉,又是Safari */
summary::-webkit-details-marker {
display: none;
}
标准的list-style: none
在所有浏览器中都有效,除了……(你能猜到吗?)……Safari。至少在这种情况下有一个专有的-webkit-
选项。
注意:另一种移除<summary>
元素标记的方法是给<summary>
元素一个不同于list-item
的display
值,例如block
或flex
。这在除……(我还需要说吗?)……Safari以外的所有浏览器中都有效。
现在我们的元素没有标记了。
没有标记完全没有任何视觉提示表明此元素是可点击的,因此仅此而已并不是一个好主意。
使用背景图像作为标记
我们可以将图像放置在背景上,如下所示:
summary {
list-style: none;
padding: 10px 10px 10px 40px;
background: url(arrow.svg) no-repeat 14px 50%;
background-size: 18px;
font-weight: bold;
}
结果如下图所示。
直接在 `<summary>
` 元素上使用背景图片的缺点是,当 `<details>
` 元素展开时,我们无法对其进行旋转,因为CSS中无法直接对背景图像设置动画。(当然,我们可以为展开状态使用不同的图像,但仍无法对其进行动画处理,这显然不够有趣。)因此,如果我们打算使用背景图像,最好将其放置在一个可以旋转和/或动画的元素上。
使用 ::after 伪元素作为标记的背景图像
让我们将背景图像置于一个 `::after
` 伪元素内:
summary {
display: flex;
}
summary::after {
content: '';
width: 18px;
height: 10px;
background: url('arrow.svg');
background-size: cover;
margin-left: .75em;
transition: 0.2s;
}
details[open] > summary::after {
transform: rotate(180deg);
}
这里有一个此代码的实时演示。
我们在 `<summary>
` 元素上使用了 `display: flex
`,以便于水平定位箭头。
这种方式的好处在于,我们可以为箭头添加动画效果。(动画在Safari中似乎不起作用,但行为已经足够好,我对这个浏览器也有点厌倦了!)
使 summary 元素看起来像一个标签
我们一直将 `<summary>
` 元素设置为全宽,但这并非必须。我们可以通过这个简单的改动,让它看起来更像一个标签:
summary {
display: inline-flex;
}
下面的例子展示了这一点。
限制 details 元素的宽度
到目前为止,我们所有的示例中,<details>
元素都自动扩展至其容器的全宽,因为它是一个块级元素。如果我们不希望它这么宽,可以设置不同的宽度,例如width: 50%;
。或者,我们可以将其设置为内联显示,使其宽度仅与内容相匹配:
details {
display: inline-block;
}
点击下面的标签,查看<details>
元素的较窄宽度。
尝试在上面的Pen中将display: inline-block
更改为width: 50%
。
将标记箭头置于summary的末端
现在,我们来点不一样的,将标记箭头放置在<summary>
元素的右侧。由于我们一直在使用display: flex
,将箭头移至最右侧只需为<summary>
元素添加justify-content: space-between
:
summary {
display: flex;
justify-content: space-between;
}
使用::after作为标记,无需背景图像
我们还可以有其他方式使用::after
而不依赖实际图像。这里有一个示例,仅使用::after
结合边框:
summary::after {
content: '';
width: 0;
height: 0;
border-top: 10px solid #15171b;
border-inline: 7px solid transparent;
transition: 0.2s;
}
这里有一个实时演示。
现在,我们拥有了一个在闭合和打开状态间旋转的箭头。同时,我们还为<details>
元素添加了漂亮的投影。
另一种不使用图像而利用::after
的方法是在content
属性中插入Unicode字符:
summary::after {
content: "\25BC";
transition: 0.2s;
}
这里我们设定一个三角形(▼)作为标记,如这个CodePen演示所示。
Unicode符号有成千上万种,探索它们相当有趣。每个符号都有一个代码,例如U + 25BC
或U + 025BC
。要在content
属性中使用这个代码,只需取加号+
后的字符,放入content
引号内,并在前面加上\
:content: "\25BC"
。如果代码开头有一个或多个零,可以省略它们。(例如,U + 02248
可以变为"\02248"
或"\2248"
。)
杂项附加
到目前为止,我们上面所做的已经足够,但还有其他有趣的东西可以尝试,让我们在这里简单玩几个。
<details>
元素的悬停效果
我们可以在<details>
元素上设置各种悬停效果。例如,我们可以这样做:
details {
transition: 0.2s background linear;
}
details:hover {
background: #dad3b1;
}
同时,让我们也在open
状态下过渡<summary>
文本颜色:
details > summary {
transition: color 1s;
}
details[open] > summary {
color: #d9103e;
}
结果如下所示。
我们也可以仅对<summary>
元素设置背景颜色变化。
动画化<details>
元素的展开与收起
哈哈,上当了吧!看来无法对 `<details>
` 元素的展开和收起进行动画处理。根据MDN:
遗憾的是,目前没有内置方法可以实现展开与收起之间的过渡动画。
尽管如此,我们还是可以通过动画处理 `<details>
` 元素的内容来增加趣味。例如,我们可以设置内容在展开时淡入显示:
details article {
opacity: 0;
}
details[open] article {
animation: fadeIn .75s linear forwards;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
效果如下所示。
另一个技巧可能是让内容滑入,就像这样:
details {
overflow: hidden;
}
details[open] article {
animation: animateUp .5s linear forwards;
}
@keyframes animateUp {
0% {
opacity: 0;
transform: translatey(100%);
}
100% {
opacity: 1;
transform: translatey(0);
}
}
效果如下所示。
虽然有点俗气,或许还有点过头,但尝试一下也无妨。不幸的是,这些动画只在第一次点击元素时有效(除非浏览器开发者工具是打开的,出于某种奇怪的原因!)。基本上需要JavaScript的介入才能让效果重复生效。
改变展开与收起状态下的summary内容
在上述示例中,无论 `<details>
` 元素是展开还是收起,`<select>
` 始终显示相同的文本。但我们可以改变这一点。首先,保留当前的“点击我”文本,同时利用 `::after
` 伪元素为每个状态添加额外文本:
summary::after {
content: " to show hidden content";
}
details[open] summary::after {
content: " to hide extra content";
}
得到的结果如下所示。
改变summary的鼠标指针样式
`
`文本上时则变为文本指针(或I形光标)。
为了好玩,我们将其改为手形光标(或“指针”):
summary {
cursor: pointer;
}
这样设置后,当鼠标悬停在`
我们也可以将光标设置在`
改变可访问性焦点样式
如果我们通过键盘浏览页面,可以按Tab键选中`
`元素有一个默认的轮廓。下图展示了在不同浏览器中的外观。
它们大致相似:基本上是一个简单、深色(蓝色或黑色)、约`3px`宽的实线轮廓。
我们可以为聚焦的`
summary:focus {outline: none;}
summary:focus-visible {outline: 3px dotted #ff0060;}
summary {padding: 10px;}
默认情况下,点击<summary>
元素时不会显示焦点轮廓。但如果我们修改焦点样式,这种样式即使在非键盘用户(即使用鼠标点击<details>
元素时)也会显示。因此,在上面的代码中,我们将outline
设置为none
,并改用focus-visible
来设定样式,这意味着焦点样式仅对键盘用户可见(对他们来说实际上是有用的)。
下图展示了我们的新样式。
这里有一个实时演示。
我们可以通过这个功能玩出很多花样,比如在<details>
元素聚焦时使用动画、背景色等。我留给你进一步探索。
使用多个details元素如同手风琴列表
目前有提议旨在协调多个details元素,使得一个关闭时另一个打开。HTML规范甚至提议为多个<details>
元素之间共享一个name
属性以实现此目的。
目前仅使用HTML和CSS无法实现此功能,但有一些巧妙的JavaScript示例可以做到,例如此处、此处和此处。
利用CSS,我们最多只能通过上述介绍的技术,使当前展开的元素与其他元素样式不同。
以下是一个简单示例:
details {
background-color: #2196F3;
}
details[open] {
background-color: #ce0e99;
}
为summary内的标题设置样式
一些注重HTML结构的开发者喜欢在<summary>
元素内放置标题元素。这样做是否有益尚存争议,但默认渲染效果不佳,标题位于箭头下方一行。通过将标题设置为display: inline
或display: inline-block
可以解决这个问题:
summary h2 {
display: inline;
}
你可以在CodePen上查看此示例的演示。
结论
如上所述,有许多简单的方法可以美化 `<details>
` 元素。设置边框、内边距和背景颜色非常简单,这些基本操作就能显著提升视觉效果。虽然有一些方法可以方便地定制默认标记,但由于Forrest的水果公司()在标记样式上存在诸多问题,可能更明智的做法是避免使用默认标记,转而创建一个完全自定义的标记元素。(尽管如此,在Safari中对标记进行样式化并不会破坏`<details>
`元素的功能。)
曾有人尝试仅用CSS实现`<details>
`元素的展开与收起动画,但这些方法充其量只能算是权宜之计,因此不值得深入探究。如果你确实需要动画效果的展开和收起,那么将需要借助JavaScript。
若想进一步了解`<details>
`元素,请参考以下资源:
如果你发现了其他有趣的`<details>
`元素样式技巧,欢迎在Twitter上与我分享,我们可能会在这里展示它们。
Source:
https://www.sitepoint.com/style-html-details-element/