Web Development

shadcn ScrollArea Gak Bisa Scroll di Dialog: Cara Fix [2026]

Asep Alazhari

ScrollArea shadcn gak bisa scroll di dalam Dialog? Viewport-nya butuh tinggi yang pasti. Ini alasan max-h gagal dan fix overflow-y-auto yang dipakai docs.

shadcn ScrollArea Gak Bisa Scroll di Dialog: Cara Fix [2026]

Kalau shadcn ScrollArea lo gak bisa scroll di dalam Dialog, gejalanya gini: list-nya ke-render, scroll mouse gak ngapa-ngapain, dan baris di bawah layar gak bisa dijangkau sama sekali. Penyebabnya masalah tinggi di CSS, bukan bug Radix atau Base UI. Viewport ScrollArea pakai height: 100%, dan tinggi persen cuma jalan kalau parent-nya punya tinggi yang pasti. Class max-h itu bukan tinggi yang pasti, jadi viewport-nya melar ngikutin semua baris dan gak ada yang bisa di-scroll.

Fix paling cepet: buang ScrollArea buat kasus ini, ganti pakai container biasa overflow-y-auto plus max-h. Itu persis yang dipakai docs Dialog shadcn/ui sekarang di contoh scrollable content-nya.

Fix Cepat

Ganti wrapper ScrollArea jadi container scroll native.

// Before: renders every row, never scrolls
<ScrollArea className="max-h-[400px]">
    {items.map((item) => (
        <ItemRow key={item.id} item={item} />
    ))}
</ScrollArea>

// After: scrolls once the list passes half the screen height
<div className="-mx-6 max-h-[50vh] overflow-y-auto px-6">
    {items.map((item) => (
        <ItemRow key={item.id} item={item} />
    ))}
</div>

Negative margin sama padding yang sama besar itu buat ngedorong scrollbar ke pinggir dialog, biar gak ngambang di samping konten. Pakai -mx-4 px-4 kalau DialogContent lo pakai p-4.

Kenapa shadcn ScrollArea Gak Bisa Scroll di Dialog Lo

Component ScrollArea dari shadcn itu cuma wrapper tipis, dan viewport di dalemnya disuruh menuhin parent-nya. Ini potongan scroll-area.tsx dari registry shadcn/ui per September 2026.

<ScrollAreaPrimitive.Root data-slot="scroll-area" className={cn("relative", className)}>
    <ScrollAreaPrimitive.Viewport data-slot="scroll-area-viewport" className="size-full rounded-[inherit] ...">
        {children}
    </ScrollAreaPrimitive.Viewport>
    <ScrollBar />
</ScrollAreaPrimitive.Root>

size-full itu jadinya width: 100%; height: 100%. Menurut referensi MDN soal height, tinggi persen cuma bisa dihitung dari tinggi parent kalau tinggi itu pasti. Pas Root cuma dikasih max-h-[400px], tingginya tetep auto, jadi 100% dari situ juga ujungnya auto. Viewport-nya jadi setinggi semua baris. clientHeight-nya sama dengan scrollHeight, dan box yang tingginya pas sama kontennya ya gak punya apa-apa buat di-scroll.

Dialog-nya bikin makin parah. DialogContent default di varian Radix itu fixed top-[50%] translate-y-[-50%] grid gap-4 p-6 sm:max-w-lg. Gak ada max height sama sekali. Jadi pas list-nya nambah panjang, dialog-nya ikut melar, dan karena posisinya di-center pakai translate, dia kepotong sama rata di atas dan bawah window. Itu kenapa tombol close sama tombol footer bisa ilang barengan.

Ini juga alasan bug-nya gak berubah walaupun sejak Juli 2026 shadcn/ui ganti default ke Base UI. Gue udah cek dua varian registry-nya, dan viewport ScrollArea versi Base UI pakai class size-full yang sama. Primitive-nya beda, aturan CSS-nya sama aja. Ini juga yang ngejelasin kenapa issue shadcn/ui #922 dengan judul “ScrollArea doesn’t work in Dialog” masih terus dapet laporan bertahun-tahun setelah dibuka.

Also Read: shadcn/ui vs Chakra UI vs MUI: Pilih yang Mana di 2026?

Cek di DevTools dalam 10 Detik

Buka dialog-nya, terus paste ini ke console browser.

const vp = document.querySelector('[data-slot="scroll-area-viewport"]');
console.log({ clientHeight: vp.clientHeight, scrollHeight: vp.scrollHeight });

Kalau dua angkanya sama, viewport lo gak punya batas tinggi dan artikel ini emang masalah lo. Kalau scrollHeight lebih gede tapi tetep gak bisa scroll, langsung lompat ke bagian Popover di bawah.

Fix 1: Pakai overflow-y-auto dengan Max Height

Container scroll native itu default yang paling pas buat list yang panjangnya berubah-ubah. Ini jalan karena overflow-y: auto digabung max-height gak butuh tinggi parent yang pasti. Box-nya ikut tumbuh sama kontennya sampai mentok batas, baru abis itu scroll.

Justru itu intinya. List tiga item dapet box pendek. List 154 item dapet batas dan bisa di-scroll. ScrollArea dengan h-[400px] fix gak bisa kayak gitu, soalnya tiga item bakal nongkrong di panel 400 pixel yang kebanyakan kosong.

Dokumentasi Dialog shadcn/ui sekarang pakai pola ini buat contoh scrollable content, baik di varian Radix, Base UI, maupun React Aria. Isinya div biasa dengan max-h-[50vh] overflow-y-auto, bukan ScrollArea.

Fix 1 bikin list-nya bisa scroll, tapi dialog yang punya form panjang di atas list masih bisa lebih tinggi dari layar. Layout yang aman itu ngebatasin seluruh dialog dan cuma body-nya yang scroll.

<DialogContent className="flex max-h-[90dvh] flex-col gap-0 p-0 sm:max-w-lg">
    <DialogHeader className="shrink-0 border-b p-6">
        <DialogTitle>Bulk edit</DialogTitle>
        <DialogDescription>{selectedIds.length} items selected</DialogDescription>
    </DialogHeader>

    <div className="min-h-0 flex-1 overflow-y-auto px-6 py-4">
        {items.map((item) => (
            <ItemRow key={item.id} item={item} />
        ))}
    </div>

    <DialogFooter className="shrink-0 border-t p-6">
        <Button variant="outline" onClick={onCancel}>
            Cancel
        </Button>
        <Button onClick={onSubmit}>Apply</Button>
    </DialogFooter>
</DialogContent>

Ada empat detail yang bikin ini jalan.

  1. flex flex-col gantiin grid bawaan. Helper cn pakai tailwind-merge, jadi class display yang belakangan menang dengan bersih.
  2. max-h-[90dvh] ngebatasin tinggi dialog. Unit dvh ngikutin viewport yang keliatan di browser mobile, jadi footer gak ketutupan address bar yang naik turun kayak yang bisa kejadian kalau pakai vh.
  3. shrink-0 di header sama footer biar mereka gak kegencet pas ruangnya abis.
  4. min-h-0 flex-1 di body biar dia ngambil sisa ruang dan boleh menyusut di bawah tinggi kontennya.

Tombol close juga tetep kejangkau, soalnya dia absolute di dalam DialogContent, yang sekarang gak bakal lewat dari 90 persen layar.

Jebakan min-h-0

Tanpa min-h-0, Fix 2 bakal gagal diem-diem, persis kayak ScrollArea tadi. Kayak yang dijelasin di referensi MDN soal min-height, flex item default-nya min-height: auto, artinya child flex nolak jadi lebih pendek dari kontennya. Jadi flex-1 emang ngelebarin body, tapi gak pernah nyusutin dia di bawah tinggi penuh 154 baris, dan overflow-y-auto lagi-lagi gak ada kerjaan.

Kalau lo bikin flex column yang harusnya bisa scroll tapi gak bisa, cek dulu ada min-h-0 atau gak sebelum ngulik yang lain. Ini alasan paling sering yang gue temuin, di dialog, sidebar, sampai panel chat.

Ini sering banget ngejebak orang yang pindahan dari Bootstrap, soalnya di sana ada class .modal-dialog-scrollable yang ngurusin semua layout-nya. Kalau lo lagi di tengah proses pindahan itu, catatan migrasi Bootstrap ke Tailwind CSS gue ngebahas sisa perpindahannya.

Kapan ScrollArea Masih Pilihan yang Bener

ScrollArea tetep oke kalau lo emang pengen scrollbar custom-nya dan bisa ngasih tinggi yang beneran. Docs ScrollArea shadcn jelas soal ini, dan contohnya pakai h-[200px].

SituasiPakai
Panjang list berubah, dari beberapa sampai ratusandiv dengan max-h dan overflow-y-auto
Panel ukuran fix, scrollbar custom yang konsistenScrollArea dengan h-72 atau h-[min(400px,50vh)]
Seluruh dialog bisa lebih tinggi dari layarFix 2, flex column yang dibatasi dengan body scroll
Scroll horizontal di ScrollArea Base UIBungkus children pakai ScrollArea.Content

Kalau lo ganti ScrollArea karena urusan layout tapi kangen scrollbar yang tipis, tambahin [scrollbar-width:thin] ke container native-nya. Catatan aja, no-scrollbar yang ada di contoh docs shadcn itu utility custom di project mereka, bukan class bawaan Tailwind.

Catatan: List Popover atau Combobox di Dalam Dialog

Ada bug lain yang mirip. Popover atau Combobox yang dibuka dari dalam Dialog nampilin list yang bisa di-scroll, scrollHeight-nya jelas lebih gede dari clientHeight, tapi scroll mouse tetep gak jalan. Yang ini penyebabnya scroll lock dari Dialog, yang ngeblok wheel event di konten yang di-portal ke luar dialog. Di varian Radix, fix yang paling sering dilaporin di GitHub issue shadcn/ui itu nambahin modal di Popover-nya biar dia ngatur scroll lock sendiri. Ini bukan masalah tinggi, jadi fix di atas gak bakal ngaruh.

Gimana Gue Kena Masalah Ini

Gue kena ini di dashboard admin pas bikin dialog bulk edit. Isinya 154 item yang bisa dipilih dalam bentuk list checkbox, semuanya udah kepilih dari awal, dibungkus ScrollArea dengan max height. Yang keliatan cuma baris yang muat di layar. Gak ada scrollbar dan scroll mouse gak ngapa-ngapain, jadi user gak bisa uncheck apa pun di bawah layar, dan di layar laptop yang lebih kecil footer dengan tombol Apply juga kepotong.

Perubahan pertama gue ganti ScrollArea jadi overflow-y-auto, dan list-nya akhirnya bisa scroll. Tapi masih gagal di layar pendek, soalnya field form di atas list ngedorong dialog lewat dari tinggi window. Perubahan kedua itu layout flex yang dibatasi dari Fix 2. Abis itu, header, tombol close, sama footer tetep di layar berapa pun jumlah item yang ke-load.

Also Read: Cara Handle 429 Rate Limit di Bulk API Request

Fix Mana yang Harus Dipakai?

Mulai dari aturan ini aja. Kalau area scroll-nya panjangnya bisa berubah, pakai container native overflow-y-auto dengan max-h. Kalau dialog-nya juga punya konten lain yang bisa tumbuh, pakai flex column yang dibatasi dari Fix 2, dan jangan lupa min-h-0 di body. Simpen ScrollArea buat panel tinggi fix yang scrollbar custom-nya emang worth dikasih tinggi eksplisit.

Pertanyaan yang Sering Diajukan

Apa bug ini masih kejadian pakai Base UI di shadcn/ui?

Masih. Per September 2026, ScrollArea shadcn versi Radix maupun Base UI sama-sama pakai viewport size-full, jadi dua-duanya butuh parent dengan tinggi yang pasti. Ganti primitive gak nge-fix ini.

Kenapa max-h gak jalan di ScrollArea tapi jalan di div biasa?

Div biasa dengan max-h dan overflow-y-auto nge-scroll dirinya sendiri, jadi cukup butuh batas punya dia. ScrollArea nge-scroll viewport di dalemnya yang ukurannya height: 100%, dan persen dari box yang cuma punya max-height ujungnya jadi auto.

Pakai vh atau dvh buat max height dialog?

Pakai dvh. Dia ngikutin viewport yang keliatan pas toolbar browser mobile muncul dan ilang, sedangkan vh pakai ukuran paling gede dan bisa ngedorong footer keluar layar di HP.

Bisa gak tetep pakai ScrollArea tapi tetep fleksibel?

Bisa, kasih tinggi eksplisit yang adaptif, misalnya h-[min(400px,50vh)]. Konsekuensinya, list pendek tetep dapet box setinggi itu dengan ruang kosong di bawahnya.

Back to Blog

Related Posts

View All Posts »