对话框

dialog 元素是一种实用的元素,可用于在 HTML 中表示任何类型的对话框,请了解其工作原理。

模态对话框是一种特殊的网页弹出式框,它会中断用户操作,以便用户专注于该对话框。弹出对话框有一些有效的应用场景,但在这样做之前应仔细考虑。模态对话框会强制用户专注于特定内容,并暂时忽略网页的其余部分。

对话框可以是模态对话框(只能与对话框中的内容互动),也可以是非模态对话框(仍然可以与对话框之外的内容互动)。模态对话框会显示在页面其余内容之上。页面的其余部分处于不活跃状态,并且默认情况下会被半透明背景遮盖。

用于创建对话框的语义 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 属性。如果元素设置了 autofocus 属性,且位于 <dialog> 内,则在网页加载时不会获得焦点(除非网页加载时对话框处于可见状态)。不过,当对话框打开时,它们会获得焦点。

默认情况下,当对话框打开时,对话框中第一个可聚焦的元素将获得焦点,除非对话框中的其他元素设置了 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" 设置为 true。 对话框还应具有可供访问的名称。如果可见文本可以提供无障碍名称,请添加 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 属性不会继承。

检验您的掌握情况

测试您对对话框元素的了解程度。

如何设置对话框后面的区域的样式?

使用 ::backdrop 伪元素。
使用 background 属性。
使用 ::background 伪元素。