对话框

模态对话框是一种特殊类型的弹出式窗口,会中断用户在网页上的操作。虽然弹出对话框有一些有效的用例,但在添加对话框之前,您应仔细考虑。模态对话框会强制用户专注于特定内容,并暂时忽略页面的其余部分。

对话框可以是:

  • 模态:用户只能与对话框中的内容互动。模态对话框会显示在页面内容上方。该页面设置为惰性,默认情况下会被半透明背景遮挡。
  • 非模态:用户可以与对话框之外的内容互动。

用于创建对话框的语义 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() 同样会打开一个对话框,但不会添加背景幕,也不会导致任何内容变为惰性。Escape 键只能关闭模态对话框,不能关闭非模态对话框。因此,提供一种关闭非模态对话框的方法就显得尤为重要。如果关闭选项位于对话框之外,焦点将返回到打开对话框的元素。这是一种不理想的用户体验。

虽然规范并未正式要求提供用于关闭对话框的按钮,但请将其视为必需。一个可见且可获得焦点的按钮可提升无障碍性和用户体验。

关闭对话框

您无需使用 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 属性会返回 true 或 false,具体取决于对话框是否可供互动,而不是它是否为模态。

虽然 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 属性。
请重试。