Mencegah Halaman di Bawah Dialog Modal Di-scroll

Saat elemen <dialog> dibuka sebagai modal menggunakan showModal(), browser akan mempromosikannya ke lapisan atas dan menandai bagian dokumen lainnya sebagai inert. Meskipun tindakan tersebut memblokir klik kursor dan fokus keyboard pada halaman yang mendasarinya, tindakan tersebut tidak mencegah scroll:

  1. Men-scroll saat kursor atau gestur sentuh berada di atas ::backdrop akan men-scroll halaman di bawahnya.
  2. Men-scroll di dalam <dialog> akan berantai ke halaman di bawahnya setelah dialog mencapai batas scroll—atau langsung jika konten dialog tidak meluap.

Sesuai dengan spesifikasi Perilaku Overscroll CSS, overscroll-behavior berlaku untuk semua elemen penampung scroll, termasuk penampung scroll yang tidak dapat di-scroll (elemen dengan overflow: hidden, atau overflow: auto yang kontennya saat ini tidak meluap). Dengan menggabungkan overscroll-behavior: contain di <dialog> dengan overflow: hidden dan overscroll-behavior: contain di dialog::backdrop, Anda dapat mencegah halaman yang mendasarinya di-scroll menggunakan CSS murni.

Penerapan

1. Membatasi perangkaian scroll pada <dialog>

Stylesheet agen pengguna menetapkan overflow: auto pada <dialog>, sehingga menjadikannya penampung scroll secara default. Terapkan overscroll-behavior: contain (atau none) ke dialog:modal (atau dialog).

2. Mengubah ::backdrop menjadi penampung scroll dan membatasi scroll-nya

Secara default, dialog::backdrop memiliki overflow: visible, yang berarti bukan penampung scroll dan mengabaikan overscroll-behavior. Anda harus menetapkan overflow: hidden di dialog::backdrop untuk menjadikannya penampung scroll yang tidak dapat di-scroll, dan menyambungkannya dengan overscroll-behavior: contain sehingga gestur scroll yang dilakukan di atas backdrop akan terperangkap dan tidak mencapai dokumen di bawahnya.

Kode Contoh

dialog:modal {
  /* MANDATORY: Prevent scroll gestures inside the modal (even when its content
     does not overflow) from chaining to the underlying page. */
  overscroll-behavior: contain;
}

dialog::backdrop {
  /* MANDATORY: ::backdrop defaults to overflow: visible (not a scroll container).
     Set overflow: hidden so it becomes a non-scrollable scroll container that
     honors overscroll-behavior. */
  overflow: hidden;
  overscroll-behavior: contain;
}

Praktik Terbaik & Batasan

  • WAJIB: Tetapkan overscroll-behavior: contain pada elemen <dialog> itu sendiri (menggunakan pemilih dialog:modal) dan dialog::backdrop. Tanpa deklarasi ini, gestur scroll di atas latar belakang atau di dalam dialog akan tetap terhubung ke halaman.
  • WAJIB: Tetapkan overflow: hidden (atau overflow: auto) di dialog::backdrop agar menjadi penampung scroll. Tanpa deklarasi ini, ::backdrop akan ditetapkan secara default ke overflow: visible dan overscroll-behavior tidak akan berpengaruh.
  • JANGAN gunakan overflow: clip atau overflow: visible di dialog::backdrop atau dialog. Kedua nilai tersebut tidak membuat penampung scroll, sehingga overscroll-behavior tidak akan berlaku.
  • JANGAN terapkan overflow: hidden atau position: fixed ke <html> atau <body> untuk mengunci scroll latar belakang saat dialog terbuka. Mengubah overflow root akan menghapus scrollbar halaman (menyebabkan pergeseran tata letak horizontal), dapat mereset atau melompati posisi scroll halaman, dan dapat merusak elemen position: sticky di halaman yang mendasarinya.

Strategi Penggantian

Meskipun properti CSS overscroll-behavior didukung di semua browser utama untuk penampung scroll yang memiliki konten tambahan, penggunaan overscroll-behavior pada penampung scroll yang tidak dapat di-scroll adalah spesifikasi baru yang tidak dapat dideteksi fiturnya.

JANGAN mencoba mendeteksi fitur dukungan penampung yang tidak dapat di-scroll dengan @supports (overscroll-behavior: contain) atau CSS.supports('overscroll-behavior', 'contain'). Semua browser modern mendukung sintaksis properti overscroll-behavior: contain dan menampilkan true, meskipun hanya menerapkannya saat konten meluap.

Sebagai gantinya, perlakukan pembatasan scroll pada penampung scroll yang tidak dapat di-scroll sebagai progressive enhancement:

  • Di browser yang mendukung overscroll-behavior pada penampung scroll yang tidak dapat di-scroll, scroll halaman latar belakang sepenuhnya dicegah baik di atas dialog::backdrop maupun di dalam <dialog> (terlepas dari apakah kontennya meluap atau tidak).
  • Di browser yang belum mendukung overscroll-behavior pada penampung scroll yang tidak dapat di-scroll, overscroll-behavior: contain pada dialog masih mencegah perantaian scroll setiap kali konten dialog itu sendiri meluap dan dapat di-scroll. Sementara itu, showModal() masih menjebak fokus keyboard dan menandai dokumen latar belakang inert.
  • Mengandalkan progressive enhancement direkomendasikan daripada solusi lama yang menerapkan overflow: hidden atau position: fixed ke <html> atau <body>, karena tidak menghapus scrollbar root, menyebabkan pergeseran tata letak horizontal, melompati posisi scroll halaman, atau merusak elemen position: sticky di halaman yang mendasarinya.