Widget disclosure adalah komponen antarmuka yang menampilkan dan menyembunyikan bagian halaman atas permintaan pengguna. Topik ini membahas dua perangkat bawaan browser untuk kebutuhan itu, yaitu pasangan details dan summary yang bekerja tanpa JavaScript sama sekali, serta elemen dialog untuk jendela modal. Dengan mengandalkan elemen bawaan, perilaku buka-tutup, fokus, dan dukungan papan ketik dikerjakan browser, sehingga skrip yang ditulis sendiri berkurang drastis.
details dan summary tanpa JavaScript#
Elemen details membentuk widget pengungkap (disclosure widget), yaitu blok yang isinya baru tampil setelah bagian judulnya diaktifkan. Elemen summary menjadi anak pertama details dan menyediakan judul yang selalu terlihat, lengkap dengan penanda segitiga yang digambar browser. Klik pada summary membuka dan menutup isinya, dan hal yang sama dapat dilakukan dari papan ketik karena summary dapat memperoleh fokus. Tanpa summary, browser menampilkan label bawaan seperti Details.
<details>
<summary>Apa isi piket hari Senin?</summary>
<p>Menyapu lantai kelas dan mengosongkan tempat sampah.</p>
</details>Atribut open, kelompok name, dan event toggle#
Status terbuka ditentukan atribut boolean open. Atribut ini membuat isi tampil sejak halaman dimuat, dan atribut yang sama berubah otomatis setiap kali pengguna membuka atau menutup widget. Perubahan status memicu event toggle pada elemen details, sehingga skrip dapat meresponsnya bila diperlukan.
Kebutuhan akordeon, yaitu sekelompok widget yang hanya boleh memiliki satu butir terbuka, ditangani atribut name. Semua details dengan nilai name yang sama membentuk kelompok, dan membuka satu butir akan menutup butir lainnya. Dukungan atribut ini tergolong baru, sehingga hanya tersedia pada browser modern terkini.
<details name="faq">
<summary>Bagaimana mengajukan perubahan jadwal?</summary>
<p>Ajukan ke ketua kelas sebelum hari Jumat.</p>
</details>
<details name="faq">
<summary>Bolehkah bertukar jadwal antarmurid?</summary>
<p>Boleh, asalkan kedua murid yang bersangkutan sepakat.</p>
</details>// tidak-dijalankan
const faq = document.querySelector("details");
faq.addEventListener("toggle", () => {
console.log(`status terbuka: ${faq.open}`);
});Skrip di atas tidak dapat dieksekusi di lingkungan Node karena memakai API browser, tetapi polanya tetap terbaca, yaitu event toggle dipasang sekali, lalu status terkini dibaca dari properti open.
Berkas utuh variasi details#
Berkas berikut mengumpulkan tiga variasi pemakaian details pada satu halaman, yaitu butir mandiri, butir yang terbuka sejak awal karena atribut open, dan kelompok akordeon dengan atribut name. Semua variasi memakai CSS sederhana yang hanya memberi bingkai dan kursor penunjuk pada summary.
Berkas ini dapat dibuka langsung di browser tanpa langkah build dan tanpa jaringan. Perhatikan bahwa tidak ada satu baris JavaScript pun di dalamnya, karena seluruh perilaku buka-tutup dikerjakan browser. Inilah alasan widget disclosure sering menjadi contoh utama elemen HTML yang menggantikan skrip, yaitu atribut dan elemen bawaan memberikan interaksi, sementara penulis hanya menyusun struktur kontennya. Saat menguji kelompok akordeon, buka butir pertama lalu butir kedua, dan amati bahwa butir pertama menutup dengan sendirinya.
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<title>Variasi details dan summary</title>
<style>
body { font-family: sans-serif; margin: 0 auto; max-width: 34rem; padding: 0 1rem; }
details { border: 1px solid #bbb; border-radius: 4px; margin: 0.5rem 0; padding: 0.25rem 0.75rem; }
summary { cursor: pointer; font-weight: 600; }
</style>
</head>
<body>
<main>
<h1>Variasi details dan summary</h1>
<details>
<summary>Apa isi piket hari Senin?</summary>
<p>Menyapu lantai kelas dan mengosongkan tempat sampah.</p>
</details>
<details>
<summary>Siapa penanggung jawab piket?</summary>
<p>Ketua piket minggu ini adalah Ali.</p>
</details>
<h2>Butir yang terbuka sejak awal</h2>
<details open>
<summary>Jadwal ini berlaku mulai kapan?</summary>
<p>Jadwal berlaku sejak minggu ini dan langsung terbuka karena atribut open.</p>
</details>
<h2>Kelompok akordeon</h2>
<details name="faq">
<summary>Bagaimana mengajukan perubahan jadwal?</summary>
<p>Ajukan ke ketua kelas sebelum hari Jumat.</p>
</details>
<details name="faq">
<summary>Bolehkah bertukar jadwal antarmurid?</summary>
<p>Boleh, asalkan kedua murid yang bersangkutan sepakat.</p>
</details>
</main>
</body>
</html>dialog untuk jendela modal#
Elemen dialog membentuk jendela percakapan yang secara default tersembunyi. Metode showModal() menampilkannya sebagai jendela modal, yaitu jendela yang berada di top layer dan menutup interaksi terhadap halaman di belakangnya hingga ditutup. Browser juga menyediakan pseudo-elemen ::backdrop untuk menggelapkan latar di belakangnya. Menekan tombol Esc menutup dialog modal tanpa skrip tambahan.
Penutupan dilakukan dari dalam dengan metode close(), atau secara deklaratif lewat formulir beratribut method="dialog". Saat dialog ditutup, event close terpicu dan properti returnValue memuat nilai tombol yang mengirimkan formulirnya. Atribut autofocus di dalam dialog menetapkan elemen yang menerima fokus saat dialog dibuka, sehingga navigasi papan ketik dimulai dari tempat yang tepat.
<dialog id="konfirmasi">
<h2>Hapus arsip catatan?</h2>
<p>Arsip lama akan dihapus permanen.</p>
<form method="dialog">
<button value="batal">Batal</button>
<button value="hapus" autofocus>Hapus</button>
</form>
</dialog>// tidak-dijalankan
const dialog = document.querySelector("#konfirmasi");
// membuka dialog secara modal, lengkap dengan backdrop
dialog.showModal();
// membaca nilai tombol yang mengirim formulirnya saat ditutup
dialog.addEventListener("close", () => {
console.log(`Dialog ditutup, returnValue = ${dialog.returnValue}`);
});Metode show() menampilkan dialog tanpa moda, artinya halaman di belakangnya tetap dapat berinteraksi, tidak ada backdrop, dan tombol Esc tidak menutupnya. Untuk kebutuhan konfirmasi yang menahan perhatian pengguna, showModal() adalah pilihan yang tepat. Adapun atribut popover yang mencapai Baseline newly available pada 2026 menawarkan alternatif deklaratif untuk konten munculan, tetapi dialog tetap menjadi pilihan dengan dukungan browser paling luas.
Demo interaktif#
Demo berikut menampilkan dialog modal yang bekerja penuh. Klik tombol Buka dialog, lalu tutup dengan tombol Batal atau Hapus di dalamnya, atau dengan tombol Esc. Latar yang menggelap berasal dari ::backdrop, dan pesan di bawah tombol menampilkan nilai returnValue setelah dialog ditutup.
Kode sumber demo
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<title>Demo elemen dialog</title>
<style>
body { font-family: sans-serif; max-width: 34rem; margin: 0 auto; padding: 0 1rem; color: #222222; }
button { padding: 6px 14px; }
dialog {
border: 1px solid #999999; border-radius: 8px;
padding: 1rem 1.25rem; max-width: 22rem;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}
dialog::backdrop { background: rgba(20, 20, 40, 0.5); }
dialog form { display: flex; gap: 0.5rem; justify-content: flex-end; margin: 0; }
#kembali { color: #555555; min-height: 1.2em; }
</style>
</head>
<body>
<p>Klik tombol untuk membuka dialog modal. Tutup dengan tombol di dalam
dialog, atau dengan tombol Esc pada papan ketik.</p>
<button id="buka" type="button">Buka dialog</button>
<p id="kembali" aria-live="polite"></p>
<dialog id="konfirmasi">
<h2>Hapus arsip catatan?</h2>
<p>Arsip lama akan dihapus permanen.</p>
<form method="dialog">
<button value="batal">Batal</button>
<button value="hapus" autofocus>Hapus</button>
</form>
</dialog>
<script>
const dialog = document.getElementById("konfirmasi");
const kembali = document.getElementById("kembali");
document.getElementById("buka").addEventListener("click", () => {
dialog.showModal();
});
dialog.addEventListener("close", () => {
kembali.textContent = "Dialog ditutup, returnValue = " + dialog.returnValue;
});
</script>
</body>
</html>Pada demo itu, menekan Hapus menutup dialog dengan returnValue = hapus, sedangkan tombol Esc menutup dengan nilai kosong. Perbedaan kecil ini sudah cukup bagi skrip untuk mengetahui jalur penutupan yang dipilih pengguna.
Kesalahan umum#
- Meniru
detailsdengan skrip toggle buatan sendiri. Penerapannya menuntut pengelolaan atributaria-expanded, fokus, dan papan ketik secara manual, sementara elemen bawaan memberikan semuanya sejak awal. - Mengharapkan backdrop dan penutupan Esc dari
show(). Kedua perilaku hanya milikshowModal(), sehingga dialog non-modal tidak cocok untuk konfirmasi yang menahan perhatian. - Menaruh tautan atau kontrol kompleks di dalam
summary. Judul pengungkap yang berisi elemen interaktif lain membingungkan navigasi papan ketik, karena satusummaryseharusnya menjadi satu sasaran aktivasi.
Ringkasan#
detailsdansummarymembentuk widget pengungkap tanpa JavaScript, dengan status terbuka pada atributopen.- Atribut
namemengelompokkandetailsmenjadi akordeon pada browser modern terkini, dan eventtogglememberi tahu perubahan status. dialogditampilkan modal denganshowModal(), lengkap dengan::backdrop, penutupan Esc, danreturnValuedari formulirmethod="dialog".show()menampilkan dialog tanpa moda untuk kebutuhan yang tidak menahan interaksi halaman.
Referensi#
- Interactive elements — HTML Living Standard — WHATWG
— Spesifikasi elemen
details,summary, dandialog. - Element: details — MDN — Dokumentasi elemen details beserta atribut open dan name.
- Element: dialog — MDN — Dokumentasi elemen dialog, metode showModal, dan pseudo-elemen ::backdrop.
- HTMLDialogElement: showModal() — MDN — Dokumentasi metode showModal untuk menampilkan dialog secara modal.