几十年来,模态对话框一直是 Web 开发中的一部分,但使用起来总是有些麻烦。模态对话框之所以如此痛苦,主要原因是很难制作一个真正符合所有可访问性标准的可访问模态对话框。这就是新的 HTML <dialog>
元素如此令人兴奋的原因。该元素使创建可访问的模态对话框变得更加容易,在本文中,我将解释您需要了解的有关这个元素的所有信息,以便在下一个项目中使用它。
什么是模态对话框?
在我们深入新的<dialog>
元素之前,我需要首先解释一下什么是模态对话框。模态对话框就是在当前页面顶部弹出的一个窗口。与普通对话框不同的是,模态对话框在打开时应该获得页面的完全控制权,阻止用户与页面进行任何其他交互,直到模态对话框关闭。而普通对话框则只是一个优先级较高的弹出窗口,允许用户在对话框打开时继续与页面交互。
我相信您在浏览网页时已经看到了大量的模态对话框,但下面是一个简单的模态对话框和普通对话框的示例,以便您可以看到两者之间的区别。
这两种对话框之间需要注意的最大区别是,当模态对话框打开时,除了滚动之外,您无法在页面上执行任何其他操作。所有其他交互都会被阻止,直到您明确关闭模态对话框。另一方面,当普通对话框打开时,您仍然可以像平常一样与页面进行交互。
<dialog>
元素基础
现在我们了解了模态对话框是什么,我们可以看看新的 HTML <dialog>
元素。实际上<dialog>
元素本身非常简单,因为它只是一个元素,只有一个可以添加到其中的自定义属性。它的作用类似于div容器,因为您可以在<dialog>
元素中放置任何您想要的内容,并且也很容易按照您想要的方式设计样式。
xml
<dialog>
<!-- 对话框内容 -->
</dialog>
默认情况下,<dialog>
元素将被隐藏,除非您将open属性添加到元素中:
xml
<dialog open>
<span>您可以看到我</span>
</dialog>
不过,不建议直接使用open属性,因为这只允许您打开非模态对话框。相反,您应该使用show()和showModal()的JavaScript方法。
dart
const dialog = document.querySelector("dialog")
dialog.show() // 打开一个非模态对话框
dialog.showModal() // 打开一个模态对话框
通过使用show()和showModal()方法,您可以准确选择您希望<dialog>
元素如何工作,因为有时您想要一个真正的模态对话框,而其他时候您想要一个更多样式的弹出对话框。要关闭一个<dialog>
元素,您只需要使用close()方法。
或者,如果您的<dialog>
元素是模态对话框,您也可以使用Esc键将其关闭。
dart
const dialog = document.querySelector("dialog")
dialog.close() // 关闭对话框
这已经使模态/弹出对话框的使用变得更加容易,但<dialog>
元素的真正好处是它默认为您处理了可访问性。我喜欢这一点,因为它使编写可访问的应用程序变得更加容易。
<dialog>
元素样式
我喜欢这个元素的另一大优点是,<dialog>
元素非常容易设计样式。有一些默认应用于<dialog>
元素的样式(取决于它是否是模态对话框),可以为您提供基础,但由于<dialog>
元素本质上只是一个更高级的div容器,您可以根据需要对其进行任意样式设置。下面的按钮将打开一个应用了以下自定义样式的对话框:
css
dialog {
z-index: 10;
margin-top: 10px;
background: green;
border: none;
border-radius: 1rem;
}
除了能够设置<dialog>
元素本身的样式之外,您还可以设置对话框打开时背景的样式,而无需任何自定义HTML或JavaScript。只要您有模态对话框,您就可以使用::backdrop伪元素设置背景样式。下面的模态对话框将以下样式应用于背景,使其呈现半透明的紫色。
css
dialog::backdrop {
background-color: hsl(250, 100%, 50%, 0.25);
}
伪元素与元素样式一样简单::backdrop,这一点结合起来,使得创建适合您网站设计风格的自定义模态对话框变得非常容易。
高级<dialog>
功能
总体而言,<dialog>
元素使用起来非常简单,但您可以使用该元素执行一些高级操作。
如果对话框中有表单,则可以将method属性设置为dialog。这将导致表单在提交时关闭对话框,最重要的是它不会提交您的表单。相反,表单数据将被保存,因此如果您重新打开同一对话框,您的表单中将包含所有相同的数据。下面是一个例子:
xml
<dialog>
<form method="dialog">
<input type="text" />
<button type="submit">提交</button>
</form>
</dialog>
另外,您可能已经注意到,在打开模态对话框时,输入框会自动获得焦点。这是您从<dialog>
元素默认获得的另一个辅助功能。
因为在表单中的任何提交按钮上,您都可以添加formmethod="dialog"属性,这个设置会导致表单在提交时只是关闭对话框,而不会真正提交表单数据。如果您想在表单中使用一个取消按钮关闭对话框而不提交表单,同时普通的提交按钮将提交表单,则这非常有用。
下面是一个例子:
xml
<dialog>
<form>
<input type="text" />
<button formmethod="dialog" type="submit">取消</button>
<button type="submit">提交</button>
</form>
</dialog>
点击外部关闭
我们习惯于在模态对话框外部单击时可以关闭模态对话框。这不是内置于<dialog>
元素中的功能,但它是很容易添加的。您需要做的就是向<dialog>
元素添加一个点击事件监听器。如果您单击模态对话框内的任意位置或::backdrop伪元素区域,则会触发此事件,因为::backdrop是<dialog>
元素的子元素。然后我们需要做的就是检查点击位置是否在<dialog>
元素内部。如果不是,那么我们可以关闭对话框。下面是一个例子:
ini
dialog.addEventListener("click", e => {
const dialogDimensions = dialog.getBoundingClientRect()
if (
e.clientX < dialogDimensions.left ||
e.clientX > dialogDimensions.right ||
e.clientY < dialogDimensions.top ||
e.clientY > dialogDimensions.bottom
) {
dialog.close()
}
})
我希望这是内置于<dialog>
元素中的功能,但幸运的是,您可以很容易地自己添加。
结论
正如您所看到的,<dialog>
元素相对易于使用,但其功能却非常强大。我喜欢创建适合您网站设计风格的自定义模态对话框和普通对话框是多么容易,以及使它们可访问性良好是多么容易。最重要的是,每个现代浏览器都支持此元素,这意味着您应该在需要对话框或模态对话框时随时使用它。