20种简单方式美化HTML details元素

本文中,我们将探讨几种简单的方法来美化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>元素有两种状态——closedopen——我们只为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-itemdisplay值,例如blockflex。这在除……(我还需要说吗?)……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 + 25BCU + 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: inlinedisplay: 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/