Kodokon kodokon.com

现代交互式 HTML:dialog、details、popover、contenteditable

用现代 HTML 的原生原语替换你的 UI 库:模态对话框、互斥的手风琴、popover 和可编辑区域。

10 分钟 · 3 题

在 Kodokon 中打开本课

<dialog> 原生地解决了多年来模态框库拼凑着实现的东西。showModal() 会把该元素投射进顶层(top layer) —— 位于任何 z-index 之上 —— 使文档的其余部分变得惰性(inert)(无法聚焦、无法点击),并暴露 ::backdrop 伪元素。而 show() 则显示一个非模态的对话框,没有惰性也没有背景遮罩。较新的 closedby=any 属性增加了点击外部即可关闭的功能。

HTML
<dialog id="confirm-dlg">
  <form method="dialog">
    <p>Delete this item?</p>
    <button value="cancel">Cancel</button>
    <button value="ok">Confirm</button>
  </form>
</dialog>
一个 method=dialog 的表单可以在不发起网络请求的情况下关闭对话框。

一个 <form method=dialog> 会在不发起网络提交的情况下关闭对话框:触发按钮的 value 会成为 dialog.returnValue,你可以在 close 事件中读取它。Escape 键会关闭一个模态对话框,方式是先发出 cancel 事件,如果输入正在进行中,你可以用 preventDefault() 取消它。

JAVASCRIPT
const dlg = document.getElementById("confirm-dlg");
dlg.showModal();
dlg.addEventListener("close", () => {
  console.log(dlg.returnValue); // "ok" or "cancel"
});
在关闭时获取用户的选择。

Popover API 无需 JavaScript 就能覆盖菜单、富提示框和 toast:把 popover 放在元素上、把 popovertarget 放在按钮上,浏览器就会处理好顶层、轻量关闭(light dismiss)(外部点击、Escape)以及 auto popover 之间的互相关闭。与 showModal() 不同,popover 不会让页面变得惰性。beforetoggletoggle 事件让你可以取消或观察每一次过渡。

HTML
<button popovertarget="user-menu">Menu</button>
<div id="user-menu" popover>
  <button>Profile</button>
  <button>Log out</button>
</div>
一个完整的菜单,没有一行 JavaScript。

<details> 无需脚本就提供了可访问的可折叠内容,而一个共享的 name 属性会创建一个互斥分组:打开一个就会关闭其他的。toggle 事件会在每次状态变化时触发。在编辑方面,contenteditable 把任何元素变成一个富文本输入区域;它的 plaintext-only 变体禁止任何标记,而 beforeinput 事件很好地替代了已废弃的 document.execCommand API。

HTML
<details name="faq" open>
  <summary>Delivery time?</summary>
  <p>Within 48 hours.</p>
</details>
<details name="faq">
  <summary>Return policy?</summary>
  <p>Within 30 days.</p>
</details>
共享的 name 产生了一个原生的互斥手风琴。

知识检测

确认你已牢记本课的重点内容。

  1. 相比 show()showModal() 多带来了什么?
    • 它会阻塞 JavaScript 执行,直到对话框关闭
    • 它把对话框放入顶层,使文档的其余部分变得惰性,并启用 ::backdrop
    • 它只是阻止页面滚动
  2. 在多个 <details> 上使用相同的 name 属性会产生什么?
    • 它们会在父表单中一起被提交
    • 什么也不会:name 不是 details 上的有效属性
    • 一个互斥手风琴:打开一个会自动关闭其他的
  3. auto popover 和 manual popover 之间的行为差异是什么?
    • auto 具有轻量关闭(外部点击、Escape)并会关闭其他的 auto popover;manual 会一直保持打开,直到被显式关闭
    • manual 不能被放入顶层
    • auto 会在页面加载时自行打开