Gọi showModal() (không phải show()) thì trình duyệt lo sẵn phần khó:
- Dialog được đưa lên top layer — nằm trên mọi nội dung khác, không bị stacking context của cha khống chế, nên hết cảnh
z-index: 9999mà vẫn bị chatransform/overflow: hiddencắt. - Nền thành inert: không click, không focus, không đọc được bằng screen reader.
- Escape đóng sẵn (kích hoạt sự kiện
cancelrồiclose). - Có
::backdropđể style lớp nền, không cần thêm div overlay. - Focus tự vào trong dialog khi mở.
html
<dialog id="dlg" aria-labelledby="dlg-title">
<h2 id="dlg-title">Xoá đơn hàng</h2>
<form method="dialog"><button value="cancel">Huỷ</button></form>
</dialog>js
const opener = document.activeElement
dlg.showModal()
dlg.addEventListener('close', () => opener.focus())Vẫn phải tự làm:
- Trả focus về phần tử đã mở — không đảm bảo trên mọi trình duyệt, cứ làm tay cho chắc.
- Accessible name: aria-labelledby trỏ tới tiêu đề (<dialog> không tự có tên).
- Khoá cuộn trang nền nếu cần.
- Đóng khi click ra ngoài: không có sẵn; tự xử lý bằng cách so event.target === dialog (vùng backdrop tính là chính dialog).
- Animation vào/ra: cần allow-discrete / @starting-style vì dialog nhảy giữa display: none và hiển thị.
- Nội dung dialog vẫn ở trong DOM khi đóng — muốn ngắt fetch hay reset form thì tự xử lý ở close.