弹出式窗口和对话框

弹出式窗口是指具有 popover 属性的任何元素,可用于各种互动模式,包括提示、提醒、Toast 等。

<div id="my-popover" popover>My popover content</div>

popover 属性默认会隐藏相应元素,您必须为用户提供一种打开该元素的方式。虽然弹出式窗口位于顶层,高于所有其他内容,但它们不是模态的。这意味着您仍然可以与弹出框之外的内容互动。

控制弹出式信息框

在探索不同类型的弹出式窗口及其行为方式之前,请先了解如何打开和关闭弹出式窗口。

以声明方式

您可以使用按钮(以及具有 button 类型的输入)和 popovertarget 属性,完全在 HTML 中控制弹出式窗口,而无需使用 JavaScript。

上一个代码段中的弹出式窗口的 idmy-popover,您可以使用此值来引用弹出式窗口。

<button popovertarget="my-popover">Toggle</button>

您还可以使用 popovertargetaction="show"popovertargetaction="hide" 指定按钮是应打开还是关闭弹出式窗口。

使用 JavaScript

您还可以使用 JavaScript 控制弹出式窗口,这在您想要显示弹出式窗口以响应除用户点击按钮之外的其他操作时非常有用。为此,您需要获取弹出式窗口元素,然后调用 showPopover()hidePopover()togglePopover()

弹出式窗口的类型

向网站添加弹出式提示框时,需要考虑很多互动。如何打开?用户如何关闭此通知?其他打开的弹出式窗口会怎么样?弹出式窗口有三种类型,您可以选择适合您的使用情形所需的行为和互动的类型。

自动弹出式窗口

自动弹出式提示框内置的功能最多,如果您未指定类型,则默认使用自动弹出式提示框。

<div id="popover" popover>My popover</div>

在许多情况下,您不希望同时打开多个弹出式窗口,因此自动弹出式窗口会在打开时关闭其他自动弹出式窗口。它们还支持“轻触即关闭”,也就是说,如果您点击弹出框外部,弹出框会自动关闭。您也可以按 Esc 键将其关闭。

手动弹出式窗口

虽然自动弹出式窗口行为涵盖了许多使用情形,但在某些情况下,您可能需要更好地控制弹出式窗口。使用手动弹出式窗口,您可以更好地控制行为,但同时也需要负责更多行为。

<div id="popover" popover="manual">My popover</div>

此弹出式信息框仅在您明确将其关闭时才会关闭,无法通过轻触关闭或按 Esc 键关闭。但允许您同时打开多个弹出式窗口。

提示浮层

您可能还想使用 Popover 为网页添加提示。在这种模式下,您希望能够将鼠标悬停在某个项目上,然后看到说明。一次只能打开一个。如果您使用自动弹出式窗口,打开一个窗口会关闭所有其他已打开的自动弹出式窗口。如果您使用手动弹出式提示框,则需要手动实现许多行为,包括关闭其他弹出式提示框。提示弹出框提供第三种选项,其行为与自动弹出框类似。不过,打开提示弹出式窗口不会关闭自动弹出式窗口。

<div id="popover" popover="hint">My popover</div>

提示弹出式窗口适用于作为主要内容的补充的次要信息。您通常希望使用悬停或聚焦等非点击事件来触发提示弹出式窗口。

放置弹出式窗口

默认情况下,弹出式窗口会在屏幕中间打开。它们会添加到顶层(位于所有其他内容之上),并且可以相对于视口进行定位。

这并不总是理想的做法,因为您通常希望将弹出式窗口放置在触发它们的项目附近。锚点定位功能可实现此目的。

锚定位置分为两个步骤:定义锚定元素,以及相对于该锚定元素放置元素。弹出式窗口可以通过为您设置隐式锚点来处理第一步。使用 <button popovertarget> 打开 popover 时,按钮是隐式锚点。如果您使用 JavaScript 打开 popover,可以使用 source 选项设置隐式锚点。

默认情况下,系统会使用 margin: auto 将悬浮框居中。如需使用锚点定位,您可能需要通过设置 margin: unset 来替换该值。

样式和动画

::backdrop 伪元素

弹出式窗口会在顶层打开,显示在页面上的所有其他内容上方。弹出式窗口下方是一个可设置样式的 ::backdrop 伪元素。

请务必注意,弹出框之外的内容并非处于非活动状态,您仍然可以点击按钮并使用键盘浏览网页。您不应遮盖网页内容,例如应用强模糊效果或将背景设置为不透明颜色。

:popover-open 伪类

假设您想使用 CSS 网格来布局弹出式窗口内容。您添加了 [popover]{ display: grid },突然间,所有弹出式窗口都显示出来了。这是因为使用 display: none 隐藏了弹出式窗口。您可以使用 :popover-open 伪类仅在弹出式窗口打开时应用样式。

[popover]{
/* Don't do this! All popovers will be visible.  */
  display: grid;
}

[popover]:popover-open {
/*  This will only affect open popovers. */
  display: grid;
}

当您为弹出式窗口添加动画效果时,:popover-open 也非常有用。

为 Popover 添加动画效果

弹出式窗口的动画包含 3 个步骤:

  1. @starting-style {popover:popover-open { } }- 弹出式窗口刚显示时的初始样式。请注意,此内容需要在样式表中定义在第 2 步之后。
  2. popover:popover-open { }- 弹出式窗口打开时的样式。
  3. popover { }- 弹出式窗口关闭时所采用的样式。

当弹出式窗口未打开时,使用 display: none 将其隐藏。如需为此添加动画效果,您需要设置 transition-behavior: allow-discrete,并将 display 添加到 transition 中的属性列表。

如果您要使用隐式锚点定位弹出式窗口,还需要在 transition 的属性列表中添加 overlay。一旦从顶层移除 popover,隐式锚定关系就会被移除,因此向 overlay 属性添加过渡效果会延迟移除操作,直到退出过渡效果完成。

Popover 之间的互动

一个网页上可能包含多个弹出式窗口,它们的互动方式取决于其类型和使用方式。

嵌套的弹出式信息框

在某些情况下,您可能需要从一个弹出式信息框内打开另一个弹出式信息框。例如,您可能有一个弹出式菜单,其中一个菜单项会打开一个子菜单。当用户关闭主菜单时,您不希望子菜单保持打开状态。弹出式窗口可以帮助您自动处理这种情况。

如果您从提示弹出式信息框打开提示弹出式信息框,或从自动弹出式信息框打开自动弹出式信息框,则这些弹出式信息框会放入堆栈中。关闭一个弹出式窗口也会关闭堆栈中位于其后的所有弹出式窗口。此功能也适用于轻触关闭 - 如果您点击某个弹出式窗口,堆栈中位于该弹出式窗口之后的所有弹出式窗口都会关闭,但之前的弹出式窗口会保持打开状态。

如果弹出式窗口的来源元素位于弹出式窗口内,则该弹出式窗口会添加到堆栈中。当您在按钮上使用 popovertarget 时,或者通过在调用 .showPopover({source}).togglePopover({source}) 时设置 source 选项来使用 JavaScript 时,系统会自动设置来源元素。

自动弹出式提示有一个堆栈,提示弹出式提示有一个单独的堆栈。不过,如果您从自动弹出式信息框内打开提示弹出式信息框,该提示弹出式信息框会添加到自动堆栈中。

请注意,提示弹出式窗口旨在显示更简单、短暂的信息,因此您无法从提示弹出式窗口触发自动弹出式窗口。

如果您使用的是手动弹出式窗口,则需要手动管理所有这些内容。

关闭其他类型的弹出式窗口

您已了解,打开自动弹出式信息框会关闭其他自动弹出式信息框,但不同类型的自动弹出式信息框之间如何互动呢?下面以一个同时使用这三种类型的网页为例,来探讨一下这种情况。有一个导航菜单,其中的按钮使用自动弹出式窗口打开和关闭。网页上有一些文字使用提示弹出框来显示上下文提示。最后,还有一个带有手动弹出式窗口的消息框,用于告知用户后台任务已完成。

提示是短暂的,会在鼠标悬停在文字上时显示。我们希望一次只显示一个提示,触发第二个提示弹出式窗口会关闭第一个提示。

当您点击某个按钮打开菜单时,提示会因以下两个原因而关闭。首先,点击提示外部会触发轻度关闭。其次,打开自动弹出式提示框会关闭所有已打开的提示弹出式框。这是因为用户已更改其关注的内容,提示弹出框中的临时内容不再相关。这意味着,如果您对自动弹出式提示框调用 showPopover(),则所有打开的提示弹出式提示框都会关闭。

下拉菜单是自动弹出式窗口。使用下拉菜单时,您希望一次只打开一个,并且打开一个会关闭另一个。如您所见,打开自动弹出式信息框也会关闭所有打开的提示弹出式信息框。

不过,在下拉菜单打开时,您可能仍想查看不相关的提示的内容。显示提示工具提示不会关闭自动弹出式窗口。

手动弹出式信息不受自动或提示弹出式信息的影响,并且在打开时不会关闭任何提示或自动弹出式信息。不过,如果您通过点击按钮打开手动弹出式窗口,这会触发提示和自动弹出式窗口的轻关闭。

不同类型的弹出式窗口之间的互动可能看起来很复杂,但如果您在正确的情况下使用这些类型,就可以实现常见的使用模式。如果您的悬浮框未按预期方式互动,请重新检查您使用的类型。

检验您的掌握情况

哪些是有效的弹出式窗口类型?

hint
正确!
auto
正确!
dialog
错误。
manual
正确!

哪些类型的弹出式窗口是模态的,这意味着背景处于非活动状态?

正确!
hint
错误。
auto
回答错误。
manual
错误。

当您打开一个 auto popover 时,系统会自动关闭哪些其他 popover?

hint
正确!
auto
正确!
manual
错误。

当您打开 hint popover 时,系统会自动关闭哪些其他 popover?

hint
正确!
auto
错误。
manual
错误。