对话框

模态对话框是网页上一种特殊类型的弹出式框:会打断用户专注于自身的弹出式窗口。有一些有效的弹出对话框用例,但在执行此操作之前应考虑清楚。模态对话框会迫使用户专注于特定内容,并暂时忽略页面的其余部分。

对话框可以是模态(只能与对话框中的内容互动)或非模态(仍然可以与对话框外部的内容互动)。模态对话框会显示在其余页面内容之上。页面的其余部分是自然的,默认情况下会被半透明背景遮挡。

用于创建对话框的语义 HTML <dialog> 元素包含语义、键盘交互以及 HTMLDialogElement 接口的所有属性和方法。

下面是一个模态 <dialog> 的示例。使用“打开模态对话框”按钮打开对话框。对话框打开后,可通过以下三种方式关闭:Esc 键、提交包含已设置 formmethod="dialog" 的按钮的表单(或者如果表单本身已设置 method="dialog")以及 HTMLDialogElement.close() 方法。

HTMLDialogElement 有三个主要方法,以及从 HTMLElement 继承的所有方法。

dialog.show() /* opens the dialog */
dialog.showModal() /* opens the dialog as a modal */
dialog.close() /* closes the dialog */

由于此 <dialog> 是通过 HTMLDialogElement.showModal() 方法打开的,因此它是一种模态对话框。打开模态对话框会停用并遮盖除对话框本身之外的所有内容。如果将鼠标悬停在对话框之外的界面上,您会注意到所有元素的行为就好像设置了 pointer-events: none; 一样;即使是打开对话框的按钮也不会对互动做出响应。

对话框打开后,焦点会移到对话框中。焦点位于该对话框中按键盘顺序导航顺序的第一个元素上。 如果您反复按 tab 键,您会注意到,当模态对话框打开时,只有对话框中的内容可以获得焦点。只要对话框处于打开状态,模态对话框以外的所有内容都会休眠。

当对话框关闭时,无论是否处于模态状态,焦点都会返回到打开对话框的元素。如果您以编程方式打开并非基于用户操作的对话框,请重新考虑。如果必须这样做,请确保将焦点放回对话框打开之前的位置,尤其是当用户没有与对话框互动就关闭对话框时。

有一个全局 inert 属性可用于停用某个元素及其所有后代(活跃的对话框除外)。使用 showModal() 打开模态对话框时,可以免费执行惰化或停用;系统不会明确设置该属性。

可以使用 ::backdrop 伪元素设置会遮挡除对话框以外所有其他内容的背景幕。仅当使用 .showModal() 方法显示 <dialog> 时,才会显示背景。该伪元素会匹配所有背景,包括使用 FullScreen API 时显示的背景,例如在全屏模式下观看视频时,该模式与屏幕或显示器的宽高比不同。

非模态对话框

HTMLDialogElement.show() 同样会打开一个对话框,但不会添加背景,也不会导致任何内容变得惰化。使用 Esc 键不会关闭非模态对话框。因此,更重要的是确保添加一种用于关闭非模态对话框的方法。这样做时,如果距离对话框较近,您会意识到焦点将转到打开对话框的元素,这可能不是最佳用户体验。

虽然规范没有正式要求提供用于关闭对话框的按钮,但应将其视为必需按钮。按 Esc 键会关闭模态对话框,但不会关闭非模态对话框。能够获得焦点的可见按钮可改进无障碍功能和用户体验。

关闭对话框

您无需使用 HTMLDialogElement.close() 方法关闭对话框。您根本不需要 JavaScript。如需在不使用 JavaScript 的情况下关闭 <dialog>,请添加带有对话框方法的表单,方法是在 <form> 上设置 method="dialog" 或对按钮设置 formmethod="dialog"

当用户通过 dialog 方法提交数据时,用户输入的数据的状态将保持不变。有提交事件时,表单会经过限制条件验证(除非设置了 novalidate)- 用户数据既不会被清除,也不会提交。不含 JavaScript 的关闭按钮可写为:

<dialog open>
  <form method="dialog">
    <button type="submit" autofocus>close</button>
  </form>
</dialog>

您可能已经注意到,在此示例中,为关闭 <button> 设置了 autofocus 属性。在 <dialog> 内设置了 autofocus 属性的元素在网页加载时不会获得焦点(除非页面在加载时对话框可见)。不过,当对话框打开时,它们将获得焦点。

默认情况下,当对话框打开时,对话框中的第一个可聚焦元素将获得焦点,除非对话框中的其他元素设置了 autofocus 属性。为关闭按钮设置 autofocus 属性可确保该按钮在对话框打开时获得焦点。但是,<dialog> 中包含 autofocus 时,只是要仔细考虑。系统会跳过自动聚焦元素之前出现的序列中的所有元素。 我们将在专题课程中进一步讨论此属性。

HTMLDialogElement 接口包含一个 returnValue 属性。使用 method="dialog" 提交表单时,会将 returnValue 设置为用于提交表单的提交按钮的 name(如果有)。如果我们编写了 <button type="submit" name="toasty">close</button>returnValue 将为 toasty

对话框打开时,系统会显示布尔值 open 属性,这意味着对话框处于活动状态,可以与之互动。当通过添加 open 属性(而不是通过 .show().showModal())打开对话框时,对话框将无模态。HTMLDialogElement.open 属性会返回 truefalse,具体取决于对话框是否可用于互动,而不是对话框是否为模态对话框。

虽然 JavaScript 是打开对话框的首选方法(包括在网页加载时添加 open 属性,然后使用 .close() 移除该属性),但有助于确保即使 JavaScript 不可用,对话框仍然可用。

其他详情

不使用 tabindex

为打开对话框而激活的元素和其中包含的关闭按钮(可能还包括其他内容)可以获得焦点并具有互动性。<dialog> 元素不具有互动性,也不会获得焦点。请勿将 tabindex 属性添加到对话框本身。

ARIA 角色

隐式角色为 dialog。如果对话框是一个确认窗口,用于传达需要确认或其他用户响应的重要消息,请设置 role="alertdialog"。对话框还应具有可供访问的名称。如果可见文本可提供无障碍名称,请添加 aria-labelledby="idOfLabelingText"

CSS 默认值

请注意,浏览器为 dialog 提供默认样式。Firefox、Chrome 和 Edge 在其用户代理样式表中设置 color: CanvasText; background-color: Canvas;,而 Safari 则在其用户代理样式表中设置 color: black; background-color: white;color 继承自 dialog,而不是 body:root,这可能出乎意料。background-color 属性未继承。

检查您的掌握程度

测试您对 dialog 元素的知识掌握情况。

如何为对话框后方设置样式?

使用 ::background 伪元素。
请重试。
使用 ::backdrop 伪元素。
正确!
使用 background 属性。
请重试。