关于 `
` 元素样式的两个问题及解决方法

Avatar of Greg Gibson
Greg Gibson

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

在不远的过去,即使是基本的类似手风琴的交互也需要 JavaScript 事件监听器或 一些 CSS… 技巧。而且,根据所使用的解决方案,编辑底层 HTML 可能会变得很复杂。

现在,<details><summary> 元素(它们组合形成所谓的 “显示部件”)使得 创建和维护这些组件变得相对简单

在我的工作中,我们使用它们来处理诸如常见问题之类的内容。

非常标准的问答格式

需要考虑几个问题

由于展开和折叠交互性已内置于 <details><summary> HTML 标签中,因此您现在可以创建显示部件,而无需任何 JavaScript 或 CSS。但您可能仍然希望使用一些。如果未设置样式,<details> 显示部件会给我们带来两个问题。

问题 1:<summary> 光标

尽管 <summary> 部分邀请交互,但元素的默认光标是文本选择图标,而不是您可能期望的指向手势

我们得到文本光标,但可能更希望使用指针来指示交互。

问题 2:<summary> 中嵌套的块级元素

<summary> 元素内嵌套块级元素(例如标题)会将该内容推到箭头标记下方,而不是保持内联

块级元素不会与摘要标记共享空间。

CSS 重置修复

为了解决这些问题,我们可以在样式表的重置部分添加以下两个样式

details summary { 
  cursor: pointer;
}

details summary > * {
  display: inline;
}

继续阅读以了解每个问题及其相应解决方案的更多信息。

更改 <summary> 光标值

当用户将鼠标悬停在页面上的元素上时,我们始终希望他们看到一个 “反映该元素上预期用户交互的光标。”

我们简要地提到了这样一个事实,尽管 <summary> 元素是交互式的(如链接或表单按钮),但其默认光标不是我们通常在这些元素中看到的指向手势。相反,我们得到 text 光标,这通常是我们期望在页面上输入或选择文本时看到的。

要解决此问题,请将光标的值切换为 pointer

details summary { 
  cursor: pointer;
}

一些著名的网站在为 <details> 元素设置样式时已包含此属性。 MDN Web 文档页面上的元素本身 正是这样做的。GitHub 也使用显示部件来处理某些项目,例如监视、加星和派生存储库的操作。

GitHub 在其显示部件菜单的 <summary> 元素上使用 cursor: pointer

我猜想选择默认的 cursor: text 值是为了指示摘要文本(以及显示部件内容的其余部分)可以被用户选中。但是,在大多数情况下,我认为更重要的是表明 <summary> 元素是交互式的。

即使在我们已将光标值从 text 更改为 pointer 之后,摘要文本仍然可以选择。请注意,更改光标仅影响外观,而不影响其功能。

将嵌套的 <summary> 内容显示为内联

在前面共享的每个 FAQ 条目的 <summary> 部分内,我通常将问题括在 适当的标题标签 中(取决于页面大纲)

<details>
  <summary>
    <h3>Will my child's 504 Plan be implemented?</h3>
  </summary>
  <p>Yes. Similar to the Spring, case managers will reach out to students.</p>
</details>

<summary> 内嵌套标题可能出于以下几个原因:

  • 一致的视觉样式。我喜欢我的 FAQ 问题看起来像页面上的其他标题。
  • 使用标题可以使 Internet Explorer 和 Chromium 之前的 Edge 版本的用户保持页面结构有效,这些版本 不支持 <details> 元素。(在这些浏览器中,此类内容始终可见,而不是交互式。)
  • 正确的标题可以帮助辅助技术用户在页面内导航。(也就是说,<summary> 元素中的标题构成了一个独特的案例,如下文详细解释。一些屏幕阅读器将这些标题解释为它们是什么,但其他一些则没有。)

标题与按钮

请记住,<summary> 元素有点奇怪。它在很多方面都像一个按钮。事实上,它甚至具有隐式 role=button ARIA 映射。但是,与按钮非常不同, 标题允许直接嵌套在 <summary> 元素内

这给我们(以及浏览器和辅助技术开发人员)带来了一个矛盾

  • 允许在 <summary> 元素中使用标题以提供页面内导航帮助。
  • 按钮会去除嵌套在其内的任何内容(如标题)的语义。

不幸的是, 辅助技术在处理这种情况方面不一致。一些屏幕阅读技术,如 NVDA 和 Apple 的 VoiceOver,确实承认 <summary> 元素内的标题。另一方面,JAWS 则不承认

这对我们来说意味着,当我们将标题放在 <summary> 内时,可以设置标题的外观样式。**但我们无法保证标题实际上会被解释为标题!**

换句话说,在那里放一个标题可能不会造成伤害。只是它可能并不总是起作用。

将所有内容设为内联

当在我们的 <summary> 内直接使用标题标签(或其他块级元素)时,我们可能希望将其 display 样式更改为 inline。否则,我们将得到一些不希望的换行,例如展开/折叠箭头图标显示在标题上方,而不是旁边。

我们可以使用以下 CSS 将 display 值应用于每个标题(以及直接嵌套在 <summary> 中的任何其他元素)

details summary > * { 
  display: inline;
}

关于此技术的几个说明。首先,我建议使用 inline,而不是 inline-block,因为当标题文本扩展到一行以上时,inline-block 仍然会出现换行问题。

其次,您可能很想替换 <summary> 元素的默认 display: list-item 值为 display: flex,而不是更改嵌套元素的 display 值。至少我是这样想的!但是,如果我们这样做,箭头标记将消失。哎呀!

额外提示:排除 Internet Explorer 的样式

我之前提到过,Internet Explorer 和 Chromium 之前的 Edge 版本(也称为 EdgeHTML)不支持<details>元素。因此,除非我们为这些浏览器使用 polyfill,否则我们可能需要确保我们的自定义展开部件样式不会应用于它们。否则,最终会出现所有内联样式都会使元素混乱的情况。

内联<summary>标题在 Internet Explorer 和 EdgeHTML 中可能会产生奇怪或不希望有的效果。

此外,当发生这种情况时,<summary>元素不再具有交互性,这意味着光标的默认text样式比pointer更合适。

如果我们决定希望重置样式仅针对合适的浏览器,我们可以添加一个功能查询,以防止 IE 和 EdgeHTML 始终应用我们的样式。以下是如何使用@supports检测仅这些浏览器支持的功能来实现此目的

@supports not (-ms-ime-align: auto) {

  details summary { 
    cursor: pointer;
  }

  details summary > * { 
    display: inline;
  }

  /* Plus any other <details>/<summary> styles you want IE to ignore.
}

IE 实际上根本不支持功能查询,因此它将忽略上述块中的所有内容,这很好!EdgeHTML确实支持功能查询,但它也不会应用块中的任何内容,因为它是唯一支持-ms-ime-align的浏览器引擎

这里的主要注意事项是,Chrome(即 12-27 版本)和 Safari(macOS 和 iOS 6-8 版本)的一些较旧版本也支持<details>,但不支持功能查询。使用功能查询意味着这些浏览器(截至 2021 年 1 月,占全球使用量的约 0.06%)也不会应用我们的自定义展开部件样式。

使用@supports selector(details)块,而不是@supports not (-ms-ime-align: auto),将是一个理想的解决方案。但选择器查询比基于属性的功能查询的浏览器支持更少

最终思考

一旦我们设置了 HTML 结构并添加了两个 CSS 重置样式,我们就可以根据需要美化所有展开部件。即使是一些简单的边框和背景颜色样式也可以极大地提升美观性和可用性。只需知道自定义<summary>标记可能会有点复杂