对话框

对话框元素是一个有用的元素,用于表示 HTML 中的任何类型的对话框,了解它是如何工作的。

模态对话框是一种特殊的网页弹出框:一种打断用户以使其专注于自身的弹出框。弹出对话框有一些有效的用例,但在这样做之前应仔细考虑。模态对话框会强制用户专注于特定内容,并(至少暂时)忽略页面的其余部分。

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

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

这是一个模态 <dialog> 的示例。使用“打开模态对话框”按钮打开对话框。打开后,有三种关闭对话框的方式:Escape 键、提交一个按钮设置了 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() 方法打开的,因此它是模态对话框。打开模态对话框会禁用并遮蔽除对话框本身之外的所有内容。如果您将鼠标悬停在对话框外部的 UI 上,您会注意到所有元素的行为都好像设置了 pointer-events: none; 一样;即使是打开对话框的按钮也不会对交互做出反应。

当对话框打开时,焦点会移入对话框。焦点设置在该对话框内顺序键盘导航顺序中的第一个元素上。如果您反复按 Tab 键,您会注意到在模态对话框打开时,只有对话框内的内容才能获得焦点。只要对话框打开,模态对话框之外的所有内容都是惰性的。

当对话框关闭时(无论是模态还是非模态),焦点都会返回到打开对话框的元素。如果您以编程方式打开对话框而不是基于用户操作,请重新考虑。如果必须这样做,请确保焦点放回到对话框打开之前的位置,特别是当用户在不与对话框交互的情况下关闭对话框时。

有一个全局 inert 属性,可用于禁用元素及其所有后代,但任何活动的对话框除外。当使用 showModal() 打开模态对话框时,惰性或停用是免费提供的;该属性未显式设置。

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

非模态对话框

HTMLDialogElement.show() 类似地打开一个对话框,但不添加背景幕或导致任何内容变得惰性。Escape 键不会关闭非模态对话框。因此,更重要的是确保您包含关闭非模态对话框的方法。这样做时,如果关闭器在对话框外部,请意识到焦点将转到打开对话框的元素,这可能不是最佳的用户体验。

虽然规范未正式要求使用按钮来关闭对话框,但请将其视为必需。Escape 键将关闭模态对话框,但不会关闭非模态对话框。能够接收焦点的可见按钮可以提高无障碍功能和用户体验。

关闭对话框

您不需要 HTMLDialogElement.close() 方法来关闭对话框。您根本不需要 JavaScript。要在没有 JavaScript 的情况下关闭 <dialog>,请包含一个带有 dialog 方法的表单,方法是在 <form> 上设置 method="dialog" 或在按钮上设置 formmethod="dialog"

当用户通过 dialog 方法提交时,用户输入数据的状态会保持。虽然有一个 submit 事件——表单会进行约束验证(除非设置了 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 属性不继承。

检查您的理解

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

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

使用 ::background 伪元素。
再试一次。
使用 ::backdrop 伪元素。
正确!
使用 background 属性。
再试一次。