- Elemen HTML `` membuat dialog modal dan non-modal native browser; dialog modal menjadikan area lain halaman berada dalam status
inert sehingga interaksi diblokir
- Cara dasar untuk membuka dan menutupnya adalah
showModal(), show(), dan close(); kontrol deklaratif juga dimungkinkan dengan ``, Invoker Commands API, dan Popover API
- Atribut
closedby membagi jalur yang dapat digunakan pengguna untuk menutup dialog menjadi any, closerequest, dan none, dengan perilaku default yang berbeda sesuai cara dialog dibuka
- Dalam aksesibilitas, fokus awal dan tombol tutup eksplisit penting; dialog yang dibuka dengan
showModal() secara default menyediakan elemen pertama yang dapat difokuskan serta penutupan dengan tombol Esc
- Untuk styling, gunakan
:modal, :open, dan ::backdrop; untuk animasi diperlukan penanganan transisi diskret seperti display, overlay, @starting-style, dan transition-behavior: allow-discrete
Peran `` dan perilaku modal
- Elemen HTML `` adalah elemen untuk membuat dialog modal dan non-modal
- Dialog modal mencegah interaksi dengan elemen UI lain dan menjadikan bagian halaman lainnya berada dalam status
inert
- Dialog non-modal tetap memungkinkan interaksi dengan bagian halaman lainnya meskipun sedang terbuka
Status terbuka dan kebijakan penutupan
- `` mencakup atribut global, tetapi atribut
tabindex tidak boleh digunakan
- `` sendiri bukan elemen interaktif dan tidak menerima fokus
- Konten internal dan tombol tutup dapat menerima fokus dan berinteraksi
- Atribut
open menunjukkan bahwa dialog sedang aktif dan dapat berinteraksi
- Jika atribut
open tidak ada, dialog tidak terlihat oleh pengguna
- Saat menampilkan dialog, penggunaan
.show() atau .showModal() lebih disarankan daripada atribut open
- `` yang dibuka dengan atribut
open bersifat non-modal
- Status buka/tutup dialog non-modal memang dapat diubah dengan toggle atribut
open, tetapi tidak disarankan
- Atribut
closedby menentukan dengan cara apa pengguna dapat menutup dialog
any: dapat ditutup dengan ketiga cara berikut
- light dismiss seperti klik atau tap di luar dialog
- Tindakan khusus platform seperti tombol Esc, tombol kembali di perangkat mobile, atau gesture dismiss
- Cara yang ditentukan developer seperti tombol yang memanggil
HTMLDialogElement.close() atau pengiriman ``
closerequest: dapat ditutup dengan tindakan khusus platform dan cara yang ditentukan developer
none: hanya dapat ditutup dengan cara yang ditentukan developer
- Jika tidak ada nilai
closedby yang valid, dialog yang dibuka dengan showModal() berperilaku seperti closerequest, sedangkan selain itu berperilaku seperti none
JavaScript dan kontrol deklaratif
- Anda dapat mengontrol langsung penampilan dan penutupan `` dengan JavaScript
showModal(): menampilkan dialog modal
show(): menampilkan dialog non-modal
close(): menutup dialog
- Dialog juga dapat ditutup dengan mengirim
di dalam menggunakan method="dialog"
- Dialog modal juga dapat ditutup dengan tombol Esc
- Invoker Commands API memungkinkan dialog modal dibuka dan ditutup hanya dengan atribut tombol
- Tetapkan atribut
commandfor dan command pada ``
- Perintah yang dapat digunakan untuk dialog adalah
"show-modal", "close", dan "request-close"
Open dialog
This dialog was opened using an invoker command.
Close
- Popover API memungkinkan dialog non-modal dibuka, ditutup, dan di-toggle secara deklaratif
- Tambahkan atribut
popover pada `` untuk menjadikannya popover
- Tetapkan
popovertarget dan popovertargetaction pada tombol atau elemen input
- Karena dialog popover bersifat non-modal, dialog dapat ditutup dengan mengklik bagian luar
- Jika nilai
popover tidak ditentukan, nilai default "auto" digunakan sehingga light dismiss aktif
popover="manual" menonaktifkan light dismiss dan memerlukan cara terpisah seperti tombol tutup
- Jika
popovertargetaction dihilangkan, nilai default toggle digunakan
Pengiriman form dan penanganan penutupan
- Semua `` memerlukan mekanisme penutupan, dan mekanisme itu harus berfungsi juga pada perangkat tanpa keyboard fisik
- Ada beberapa cara untuk menutup dialog
- Mengatur
method="dialog" pada di dalam lalu mengirimnya
- Klik di luar dialog saat light dismiss aktif
- Menekan tombol Esc pada dialog yang mengizinkannya
- Memanggil
HTMLDialogElement.close()
formmethod="dialog" pada `` atau tombol submit akan menutup dialog
- Status kontrol form disimpan, tetapi tidak dikirim
returnValue diatur ke nilai tombol yang diaktifkan
- Pada form dengan input wajib, user agent mencegah dialog ditutup lewat pengiriman biasa sampai nilai diberikan
- Menggunakan
formnovalidate pada tombol tutup dapat melewati validasi form
- Dialog juga dapat ditutup dengan memanggil
dialog.close() dari JavaScript
Fokus dan aksesibilitas
- Saat `` dibuka dengan
showModal(), fokus secara default diatur ke elemen bersarang pertama yang dapat difokuskan
- Untuk menentukan posisi fokus awal yang paling tepat pada dialog tertentu, Anda dapat menggunakan atribut
autofocus
- Jika tidak ada elemen yang perlu segera diinteraksikan, disarankan menaruh
autofocus pada tombol tutup
- Jika posisi fokus awal tidak pasti, seperti pada dialog yang dirender secara dinamis, `` itu sendiri dapat menjadi posisi fokus awal yang tepat
- Cara paling kuat adalah menyertakan tombol eksplisit seperti tombol konfirmasi, batal, atau tutup agar semua pengguna dapat menutup dialog
- Dialog yang dipanggil dengan
showModal() secara default ditutup dengan tombol Esc
- Dialog non-modal secara default tidak ditutup dengan tombol Esc
- Pengguna keyboard mengharapkan dialog modal dapat ditutup dengan tombol Esc
- Jika beberapa dialog modal terbuka, tombol Esc hanya boleh menutup dialog yang terakhir ditampilkan; browser menyediakan perilaku ini saat menggunakan ``
- `` native menyediakan fitur kegunaan dan aksesibilitas yang harus direplikasi sendiri pada dialog kustom yang dibuat dari elemen lain
- Browser mengekspos `` secara mirip dengan dialog kustom yang menggunakan ARIA
role="dialog"
- `` yang dipanggil dengan
showModal() secara implisit memiliki aria-modal="true"
- `` yang ditampilkan dengan
show(), atribut open, atau perubahan display default diekspos sebagai aria-modal="false"
- Saat mengimplementasikan dialog modal, semua hal selain `` dan kontennya harus dirender sebagai
inert; saat menggunakan showModal(), browser menyediakan perilaku ini
Styling CSS dan backdrop
- `` dapat dipilih berdasarkan nama elemen seperti elemen biasa
- Untuk styling berbasis status, pseudo-class
:modal dan :open dapat digunakan
- Latar belakang dialog modal dapat diberi styling dengan pseudo-element
::backdrop
- Diterapkan pada backdrop yang muncul di belakang `` saat dialog ditampilkan dengan
showModal()
- Dapat memburamkan, menggelapkan, atau menutupi konten di belakang yang berada dalam status inert
Pola penggunaan lewat contoh
- Contoh Invoker Commands API membuka dialog dengan tombol
command="show-modal" dan menutupnya dengan tombol command="close"
- Dapat dibuka dengan tombol “Open dialog”
- Dapat ditutup dengan tombol “Close” atau tombol Esc
- Contoh Popover API membuka dan menutup dialog non-modal dengan
popover, popovertarget, dan popovertargetaction
- Dapat ditutup dengan tombol “Close”, tombol Esc, atau memilih bagian luar dialog
- Jika menggunakan
popover="manual", light dismiss dinonaktifkan
- Contoh atribut
open membuat dialog non-modal HTML-only yang sudah terbuka saat halaman dimuat
- Dapat ditutup dengan tombol “OK” pada ``
- Tidak tersedia cara untuk membukanya lagi setelah ditutup
- Untuk menampilkan dialog non-modal, penggunaan
HTMLDialogElement.show() lebih disukai
- Contoh dialog modal membukanya dengan
.showModal() dan menutupnya dengan close()
- Styling latar gradien dilakukan dengan
::backdrop
- Saat dialog terbuka, bagian luar dialog menjadi inert sehingga tidak dapat berinteraksi dengan dokumen
- Contoh
returnValue menangani nilai kembalian dialog melalui form dan nilai tombol
returnValue default adalah string kosong, atau nilai tombol yang mengirim form di dalam dialog
- Tombol “Confirm” meneruskan nilai pilihan ke
close() untuk digunakan sebagai nilai kembalian
- Jika ditutup dengan tombol Esc,
returnValue tidak diperbarui dan event close juga tidak terjadi sehingga teks `` tidak diperbarui
Animasi ``
yang tersembunyi menjadi `display: none`, sedangkan yang ditampilkan menjadi display: block
- Saat status tampilan berubah, elemen ditambahkan ke atau dihapus dari top layer dan accessibility tree
- Untuk menganimasikan ``, properti
display harus dapat dianimasikan
- Browser yang mendukungnya menangani
display sebagai animasi diskret
- Saat berubah dari
none ke block, perubahan ke block terjadi pada titik 0% sehingga elemen terlihat selama seluruh animasi
- Saat berubah dari
block ke none, perubahan ke none terjadi pada titik 100% sehingga elemen terlihat selama seluruh animasi
-
Animasi dengan CSS transition
- Untuk menganimasikan `` dengan CSS transition, fitur berikut diperlukan
@starting-style: menyediakan nilai awal transisi setiap kali dialog dibuka
- Transisi
display: mempertahankan dialog pada nilai display yang terlihat selama transisi
- Transisi
overlay: menunda penghapusan dari top layer hingga transisi selesai
transition-behavior: allow-discrete: mengaktifkan transisi diskret untuk display dan overlay yang secara default tidak dianimasikan
- Pada browser yang tidak mendukung pseudo-class
:open, status terbuka dapat diberi styling dengan selector atribut dialog[open]
- Karena `` berubah dari
display: none ke display: block setiap kali ditampilkan, setiap transisi masuk beralih dari @starting-style ke gaya dialog:open
-
Animasi keyframe
- Animasi CSS keyframe memiliki batasan yang berbeda dari transition
- Tidak menyediakan
@starting-style
- Menyertakan nilai
display di dalam keyframe
- Tidak perlu mengaktifkan
allow-discrete secara eksplisit
overlay juga tidak perlu diatur di keyframe
- Fade-out backdrop tidak dapat dianimasikan karena backdrop langsung dihapus dari DOM saat dialog ditutup
Ringkasan teknis
- Kategori konten: flow content, sectioning root
- Konten yang diizinkan: flow content
- Tag awal dan tag akhir sama-sama wajib, dan tidak ada penghilangan tag
- Parent yang diizinkan: semua elemen yang menerima flow content
- Peran ARIA implisit:
dialog
- Peran ARIA yang diizinkan:
alertdialog
- Antarmuka DOM:
HTMLDialogElement
- Spesifikasi: HTML # the-dialog-element
1 komentar
Komentar Hacker News
Elemen HTML yang dapat berinteraksi mencakup pemilih berkas, pemilih warna, pemilih tanggal/waktu, slider angka, opsi rekomendasi pada kolom teks, ringkasan/detail yang dapat dibuka, FAQ, dan pemutar media dengan kontrol.
Elemen-elemen seperti ini bagus karena ringan dan semantik, dan
<details>yang berbaginameyang sama juga dapat berperilaku menutup item sebelumnya saat salah satunya dibuka.Semoga implementasinya bisa lebih baik.
Saya sudah memakai
<dialog>sejak 2019, dan meskipun Firefox serta Safari belum mendukungnya selama beberapa tahun lagi, kualitas polyfill dari Google cukup baik sehingga saya menggunakannya tanpa masalah di produksi SaaS untuk bisnis.Hal yang paling mengecewakan adalah elemennya hampir tidak diberi styling. Hanya ada border piksel hitam tebal yang sangat dasar dan sudut-sudut tajam, berbeda dari harapan saya bahwa browser akan mengikuti konvensi penempatan dialog/jendela sistem operasi sehingga terlihat seperti dialog native macOS, iOS, atau Windows.
Karena elemen yang terbuka berada di lapisan teratas yang terpisah, saya juga berharap ia bisa keluar hingga di luar viewport browser, tetapi harapan itu pun pupus. Dari sudut pandang pengguna, mereka tidak menginginkan popup atau dialog modal yang tidak bisa dipindahkan dan sepenuhnya menutupi isi dokumen.
Para vendor browser tampaknya ingin kita tidak menggunakan
alert(),prompt(), danconfirm()karena semuanya memblokir JavaScript/main thread, tetapi mereka belum menghadirkan API pengganti yang sama sederhananya, efektif, dan tidak menuntut kemampuan desain UI. Alih-alih mencoba meyakinkan bahwa<dialog>selalu lebih baik di semua situasi, akan lebih baik jika mereka menyediakan API alert/prompt/confirm non-pemblokir berbasis Promise.Bahwa fitur-fitur baru tidak lagi berperilaku seperti keluarga
alert()lama bukan sekadar kekecewaan yang kebetulan, tetapi juga ada sisi baiknya.Namun gaya default
<dialog>semestinya sedikit lebih diperhatikan; meskipun tidak 100% terlihat dan berperilaku seperti dialog sistem di luar DOM, sekadar memiliki gaya default yang cocok dengan gaya bawaan browser saja sudah akan jauh lebih baik.Untuk aplikasi web yang punya lebih banyak izin daripada halaman biasa, seperti PWA, arah seperti ini mungkin bisa lebih diterima, mirip fitur terpisah untuk styling jendela atau berinteraksi dengan sistem.
<dialog>terlihat seperti jendela browser native, itu bisa mengaburkan line of death.Situs web berbahaya akan lebih mudah menampilkan popup “pembaruan browser” di tengah halaman, lalu mengalihkan pengguna ke halaman unduhan Chrome yang tampak meyakinkan untuk membuat mereka mengunduh executable yang sudah dimodifikasi.
https://textslashplain.com/2017/01/14/the-line-of-death/
Pengguna membuka banyak tab, dan informasi yang diperlukan untuk menyelesaikan dialog bisa saja berada di tab lain.
Kita juga harus sangat berhati-hati soal seberapa besar kendali visual yang diberikan ke dialog sebenarnya. Terutama jika dibuat tampak seperti sistem operasi; bahkan sekarang pun banyak orang tertipu oleh peringatan virus browser palsu, dan dialog yang tampak asli serta wajib diinteraksikan dapat sangat meningkatkan tingkat keberhasilan serangan.
Sebagian besar perusahaan tempat saya bekerja memiliki bahasa desain yang cukup konsisten, dan apa pun kata orang yang menyukai HTML/CSS murni, memakai komponen bawaan browser apa adanya hampir selalu terlihat canggung dan amatiran.
Jika masalah ini tidak diselesaikan, sulit bagi komponen seperti ini untuk dipakai luas.
alert(),prompt(), danconfirm()bekerja sepertiawait Prompts.alert("This is an alert message!");,await Prompts.confirm(...), danawait Prompts.prompt(...).Demo: https://tools.simonwillison.net/prompts-js
Kodenya ditulis oleh o1: https://chatgpt.com/share/67539c28-4df0-8006-b021-4f468e011f...
Saya menulis artikel berjudul “The HTML dialog element API is a mess”: https://lapcatsoftware.com/articles/2024/2/1.html
Meski begitu, nilainya ada pada fakta bahwa ia adalah standar. Web itu hebat karena berjalan di mana saja, dan memang tidak mungkin tidak berantakan
Dalam konteks ini, menurut saya
<dialog>adalah keberhasilan, terutama untuk tool manajemen internal. Saya tidak peduli dengan tren frontend terbaru; saya hanya ingin menampilkan konten sebagai overlay modal di atas tampilan utama sambil menghemat ruang layarUntuk membuka dialog diperlukan input pengguna, dan dialog modal memblokir input pengguna, jadi agar ini terjadi, input di dalam dialog harus membuka dialog itu lagi
Jika membuka dialog lewat pekerjaan asinkron, Anda harus melacak mana yang sedang terbuka dan tertutup; hal serupa juga terjadi di lingkungan seperti Qt
<dialog>menjadi semacam versi lebih kuat dari await confirm/prompt yang dapat dikustomisasi dan tidak memunculkan peringatan berbeda-beda antar-browser meski dibuka beberapa kaliNamun pada praktiknya, ia lebih mirip
divyang dipercantikCompression Streams API tidak buruk, tetapi itu API yang sangat kecil
Melihat polanya, rasanya Google kurang baik dalam menangani pengalaman pengguna dan pengalaman developer
Sebagai tambahan, setelah mencari posisi standar, ternyata keduanya mendukung URLPattern
Terlepas dari implementasinya, menurut saya ini adalah satu langkah ke arah yang benar
Saat ini juga ada proposal yang tampaknya memperkuat
<select>: https://open-ui.org/components/combobox.explainer/Untuk notifikasi toast, Popover API sudah masuk ke browser: https://mdn.github.io/dom-examples/popover-api/
Ada juga proposal popover hint untuk tooltip: https://open-ui.org/components/popover-hint.research.explain...
Saya suka elemen
<dialog>, terutama pertimbangan aksesibilitas yang sudah bawaan dan terstandardisasiSaya menantikan hari ketika bisa menggunakannya tanpa polyfill setelah Safari di bawah 15.4 keluar dari kriteria dukungan
Namun keluhan terbesar saya adalah ketergantungannya pada JavaScript. Hampir semua pengunjung situs memang akan datang dengan JavaScript aktif, tetapi ada kepuasan tersendiri saat membuatnya tidak harus begitu
Saya tidak tahu mengapa status terbuka dialog tidak bisa dikendalikan dengan CSS atau tombol target, dan saya ingin tahu jika saya keliru
popover=""Elemen itu mudah dijadikan target oleh tombol, tidak membutuhkan JavaScript sisi klien, dan bisa ditutup dengan mengklik area luar. Ini perilaku yang tidak ada secara default pada
<dialog>Saya tidak yakin soal aksesibilitasnya, tetapi rasanya tidak lebih buruk daripada cara lama memakai label/checkbox/elemen form tersembunyi, jauh lebih sederhana, dan tidak terasa terlalu seperti hack
https://css-tricks.com/invoker-commands-additional-ways-to-w...
Akan menyenangkan jika HTML mendukung konsep tag seperti
<page>yang dapat mendefinisikan beberapa halaman dalam satu file dan menampilkannya satu per satuTanpa terlihat seperti dialog, setiap PAGE bisa menarik bagian umum seperti header, sidebar, dan footer di halaman yang sama bergantung pada status terpilihnya
Sekarang ini memang bisa dilakukan dengan menyembunyikan dan menampilkan
div, tetapi dukungan pendekatan seperti ini lewat tag HTML tertentu bisa membantuSaat mencobanya hari ini, ada masalah yang tidak bisa saya atasi dengan workaround
Jika ada form di dalam dialog, ketika menekan Enter saat fokus berada pada input atau menekan Space saat fokus berada pada tombol submit, dialog ikut tertutup bersamaan dengan submit form
Saya tidak menemukan cara yang rapi untuk mencegahnya. Biasanya form memuat ulang halaman, jadi ini mungkin bukan masalah umum, tetapi di sini saya memakai htmx
Saya memakai editor yang memperbarui iframe lewat form di dalam
<dialog>, dan iframe target saja yang dimuat ulang; dialognya tidak tertutupSaya juga tidak bisa mereproduksi kasus dialog tertutup saat menekan Enter. Itu seharusnya sama dengan
submit, dansubmitjuga tidak menutup dialogSebagai catatan, kemarin saya baru tahu bahwa tombol bisa menutup dialog
preventDefaultdanstopPropagation?Saat mencari pengelola persetujuan cookie untuk build baru yang sudah dioptimalkan, saya tidak suka opsi open source yang ukurannya lebih dari 100KB, jadi saya membuat sendiri: https://github.com/replete/biscuitman
Saya mengandalkan
<dialog>agar bisa menulisnya sekecil mungkin, dan dengan hanya beberapa aturan CSS, ia tetap berjalan secara native bahkan tanpa stylingPada akhirnya saya juga sampai membuat tool build yang mengompilasi hingga IE11 dan versi browser yang benar-benar tua
<dialog>umumnya bekerja dengan baik, dan di browser lama memang perlu sedikit trik CSS, tetapi tidak sulit ditangani. Ini tambahan yang bagus untuk platform web, tetapi setelah melakukan pekerjaan ini selama 20 tahun, saya tidak ingin harus membuat ulang kontrol multi-select kustom setiap beberapa tahun. Kontrol native itu bagusPerilaku tutup yang umum di sebagian besar contoh tidak berfungsi di Android Firefox
autofocuspada tombol tutup tidak berfungsiAkhirnya setiap kali memanggil
show(), saya menambahkan baris seperti$('#thatModal *[autofocus]').focus()Menurut MDN, secara default seharusnya berfungsi sesuai yang dimaksud
Sepertinya hanya listener yang ditambahkan lewat JavaScript yang berfungsi dengan benar