让我们探索一下
使用的核心方面
HTML 标签创建一个默认隐藏的对话框,可以用作弹出窗口或模态窗口。
弹出窗口经常用于显示简单的通知,例如 Cookie 消息、消失的 Toast 警报、工具提示或右键单击上下文菜单元素。
模态窗口帮助用户专注于特定任务,例如需要用户确认的通知和警告、复杂的交互表单以及图像或视频的灯箱。
弹出窗口不会阻止与页面的交互,而模式窗口会覆盖文档、使背景变暗并阻止其他操作。此行为无需额外的样式或脚本即可实现;唯一的区别是打开对话框的方法。
对话框窗口打开方法
— 弹出窗口:
<dialog>
<pre class="brush:php;toolbar:false">const popUpElement = document.getElementById("pop-up");
popUpElement.show();
登录后复制
登录后复制
—模态窗口:
<dialog>
<pre class="brush:php;toolbar:false">const modalElement = document.getElementById("modal");
modalElement.showModal();
登录后复制
登录后复制
在这两种情况下,打开<对话框>标签将其 open 属性设置为 true。直接设置它会将对话框作为弹出窗口而不是模式打开。要渲染模态窗口,您必须使用适当的方法。不需要 JavaScript 来创建最初打开的弹出窗口。
<dialog open>Hi, I'm a popup!</dialog>
登录后复制
登录后复制
登录后复制
登录后复制
尝试一下:
- 使用 .show() 方法打开弹出窗口:https://codepen.io/alexgriss/pen/zYeMKJE
- 使用 .showModal() 方法打开模态窗口:https://codepen.io/alexgriss/pen/jOdQMeq
- 直接更改open属性:https://codepen.io/alexgriss/pen/wvNQzRB
对话框窗口关闭方法
对话框窗口以相同的方式关闭,无论它们如何打开。以下是关闭弹出窗口或模式窗口的几种方法:
——使用 .close() 方法:
<dialog>
<pre class="brush:php;toolbar:false">const popUpElement = document.getElementById("pop-up");
popUpElement.show();
登录后复制
登录后复制
——通过使用 method="dialog" 属性触发表单中的提交事件:
<dialog>
<pre class="brush:php;toolbar:false">const modalElement = document.getElementById("modal");
modalElement.showModal();
登录后复制
登录后复制
— 按 Esc 键:
使用 Esc 关闭仅适用于模式窗口。它首先触发取消事件,然后关闭,从而可以轻松警告用户表单中未保存的更改。
尝试一下:
- 使用 close 方法关闭对话框:https://codepen.io/alexgriss/pen/GRzwjaV
- 通过提交表单关闭对话框:https://codepen.io/alexgriss/pen/jOdQVNV
- 使用 Esc 键关闭模态窗口:https://codepen.io/alexgriss/pen/KKJrNKW
- 防止模式窗口通过 Esc 关闭:https://codepen.io/alexgriss/pen/mdvQObN
关闭时返回值
当使用method="dialog"属性关闭带有表单的对话框时,您可以捕获提交按钮的值。如果您想根据单击的按钮触发不同的操作,这非常有用。该值存储在 returnValue 属性中。
尝试一下:https://codepen.io/alexgriss/pen/ZEwmBKx
仔细看看它是如何工作的
让我们更深入地了解对话框窗口的机制及其浏览器实现的细节。
弹出窗口的机制
打开一个<对话框>作为带有 .show() 的弹出窗口或 open 属性会自动将其定位为 DOM 中的position:absolute。基本 CSS 样式(例如边距和边框)应用于元素,窗口内的第一个可聚焦项目将通过 autofocus 属性自动获得焦点。页面的其余部分保持互动。
模态窗口的机制
模态窗口的设计和工作方式比弹出窗口更复杂。
文档叠加
使用 .showModal() 打开模态窗口时,
层的概念指的是堆叠上下文,它定义了元素如何沿着相对于用户的Z轴定位。在 CSS 中设置 z-index 值会为元素创建一个堆叠上下文,其中子元素的位置是在该上下文中计算的。模态窗口始终位于该层次结构的顶部,因此不需要 z-index。
在 MDN 上了解有关 堆叠上下文 的更多信息。
要了解有关顶层中呈现的元素的更多信息,请访问 MDN。
文件拦截
当模态元素在顶层渲染时,会创建一个与可见文档区域大小相同的 ::backdrop 伪元素。即使设置了指针事件:未设置 CSS 规则,此背景也会阻止与页面其余部分的交互。
除了模态窗口之外的所有元素都会自动设置 inert 属性,阻止用户操作。它会禁用单击和焦点事件,并使屏幕阅读器和其他辅助技术无法访问这些元素。
在 MDN 上了解有关 inert 属性的更多信息。
专注行为
当模式打开时,其中的第一个可聚焦元素会自动获得焦点。要更改最初聚焦的元素,可以使用 autofocus 或 tabindex 属性。无法为对话框元素本身设置 tabindex,因为它是页面上唯一不应用惰性逻辑的元素。
对话框关闭后,焦点返回到打开它的元素。
解决模态窗口的用户体验问题
不幸的是,
滚动阻塞
尽管原生 HTML5 模式窗口创建了一个 ::backdrop 伪元素来阻止与其下方内容的交互,但页面滚动仍然处于活动状态。这可能会分散用户的注意力,因此建议在模式打开时截断正文的内容:
<dialog>
<pre class="brush:php;toolbar:false">const popUpElement = document.getElementById("pop-up");
popUpElement.show();
登录后复制
登录后复制
登录后复制
每次打开和关闭模态窗口时,都必须动态添加和删除这样的 CSS 规则。这可以通过操作包含以下 CSS 规则的类来实现:
<dialog>
<pre class="brush:php;toolbar:false">const modalElement = document.getElementById("modal");
modalElement.showModal();
登录后复制
登录后复制
登录后复制
如果 :has 选择器的支持状态满足项目的要求,您也可以使用。
<dialog open>Hi, I'm a popup!</dialog>
登录后复制
登录后复制
登录后复制
登录后复制
尝试一下:https://codepen.io/alexgriss/pen/XWOyVKj
通过单击窗口外部关闭对话框
这是模态窗口的标准 UX 场景,可以通过多种方式实现。这里有两种方法可以解决这个问题:
基于 ::backdrop 伪元素行为的方法
单击 ::backdrop 伪元素被视为单击对话框元素本身。因此,如果将模式窗口的整个内容包装在附加的
中,然后覆盖对话框元素本身,您可以确定单击的方向 - 在背景上还是在模式窗口内容上。
不要忘记重置浏览器的的默认填充和边框样式。防止模态窗口因意外点击而关闭的元素:
<dialog>
<pre class="brush:php;toolbar:false">const popUpElement = document.getElementById("pop-up");
popUpElement.show();
登录后复制
登录后复制
登录后复制
现在,我们将模态窗口边框和边距的常见样式仅应用于内部包装器。
我们需要编写一个函数,仅在单击背景而不是内部包装元素时关闭模态窗口:
<dialog>
<pre class="brush:php;toolbar:false">const modalElement = document.getElementById("modal");
modalElement.showModal();
登录后复制
登录后复制
登录后复制
尝试一下:https://codepen.io/alexgriss/pen/mdvQXpJ
一种基于确定对话框窗口大小的方法
此方法与第一个方法不同,第一个方法需要一个额外的包装器来容纳模态内容。在这里,您不需要任何额外的包装。所需要做的只是检查单击时光标的位置是否超出元素区域:
<dialog open>Hi, I'm a popup!</dialog>
登录后复制
登录后复制
登录后复制
登录后复制
尝试一下:https://codepen.io/alexgriss/pen/NWoePVP
设置对话框窗口的样式
element 在样式方面比许多原生 HTML 元素更灵活。以下是一些对话框窗口样式的示例:
使用 ::backdrop 选择器设置背景样式:https://codepen.io/alexgriss/pen/ExrOQEO
动画对话框窗口打开和关闭:https://codepen.io/alexgriss/pen/QWYJQJO
作为侧边栏的模态窗口:https://codepen.io/alexgriss/pen/GRzwxgr
无障碍
很长一段时间,元素存在一些辅助功能问题,但现在它可以很好地与屏幕阅读器等主要辅助技术配合使用(VoiceOver、TalkBack、NVDA)。
当出现时打开后,屏幕阅读器会将焦点移至对话框。对于模态窗口,焦点保留在对话框内,直到它关闭。
默认情况下,元素被辅助技术识别为具有 ARIA 属性 role="dialog"。模态对话框将被识别为具有 ARIA 属性 aria-modal="true"。
以下是一些提高
咏叹调标记者
始终在对话框窗口中包含标题,并为
<dialog>
<pre class="brush:php;toolbar:false">const popUpElement = document.getElementById("pop-up");
popUpElement.show();
登录后复制
登录后复制
登录后复制
如果您需要设置 ::backdrop 伪元素的样式,请确保将这些样式也应用到相应的 .backdrop 元素,以确保与旧版浏览器的兼容性:
<dialog>
<pre class="brush:php;toolbar:false">const modalElement = document.getElementById("modal");
modalElement.showModal();
登录后复制
登录后复制
登录后复制
建议通过动态导入连接polyfill,并且仅适用于不支持
<dialog open>Hi, I'm a popup!</dialog>
登录后复制
登录后复制
登录后复制
登录后复制
结论
原生 HTML5
在本文中,我们讨论了以下主题:
- 出现问题元素求解;
- 与的交互元素的 API;
- 对话框窗口如何在浏览器级别工作;
- 模态框的常见问题及其解决方案;
- 改进了的可访问性屏幕阅读器等辅助技术的元素;
- 扩展浏览器对
最后,我邀请您查看纯 JS 中的模态窗口组件实现,其中考虑了文章中讨论的主要方面:https://codepen.io/alexgriss/pen/abXPOPP
这就是我想分享的关于使用