Halaman dokumen menggulir utuh dari atas ke bawah; dashboard tidak. Pada aplikasi web, kerangkanya — sidebar dan header — tetap diam, dan hanya area isinya yang menggulir. Perilaku ini disebut app shell, dan dicapai dengan satu kombinasi yang belum kita rakit sebelumnya: grid berperilaku setinggi viewport plus overflow pada area tertentu. Chapter ini sekaligus menjadi bukti komposisi: hampir semua bagiannya adalah pola yang sudah kita buat di section ini.

Kerangka App Shell Setinggi Viewport #

css
.shell {
  display: grid;
  height: 100dvh;
  grid-template-columns: minmax(220px, 260px) 1fr;
  grid-template-rows: auto 1fr;
  grid-template-areas: "samping kepala" "samping isi";
  overflow: hidden;
}

Perhatikan bedanya dengan layout sidebar yang kita rakit sebelumnya. Di sana, halaman menggulir utuh dan sidebar memakai position: sticky untuk tetap terlihat. Di sini strateginya berbalik: height: 100dvh mengunci kerangka pada tinggi viewport, overflow: hidden mencegah halaman ikut menggulir, dan baris auto 1fr memberi header tinggi sesuai isinya lalu menyerahkan sisa tinggi kepada area isi. Sidebar pun tidak butuh sticky — dia memang tidak pernah bergerak.

Area Isi yang Menggulir #

Kunci terakhir pola ini adalah satu deklarasi yang mudah terlewat:

css
.area-isi {
  grid-area: isi;
  overflow-y: auto;
  min-height: 0;
  padding: 24px;
}

min-height: 0 terlihat mencurigakan, tetapi inilah bagian terpenting pola ini. Item grid secara default tidak boleh lebih kecil dari kontennya (ukuran minimum otomatis, persis seperti 1fr yang meluber pada layout sidebar). Tanpa min-height: 0, konten yang panjang memaksa baris 1fr bertambah tinggi melebihi shell, dan seluruh halaman kembali menggulir — pola ini gagal diam-diam. Dengan min-height: 0, area isi menerima tinggi berapa pun yang disediakan barisnya, lalu overflow-y: auto mengurus sisanya di dalam.

Merangkai Pola-Pola Sebelumnya #

App shell adalah titik temu dari section ini. Setiap wilayahnya adalah pola yang sudah kita rakit sebagai chapter tersendiri:

WilayahPola yang dipakaiSumbernya
HeaderLatar penuh dengan baris flex brand plus aksiPola: Header dan Navigation
SidebarKolom minmax(220px, 260px) dengan daftar menuPola: Sidebar Layout
Grid kartu statistikrepeat(auto-fit, minmax()) di dalam area isiPola: Card Grid
Laporan selebar penuhgrid-column: 1 / -1 di dalam grid kontenPola: Card Grid dan materi grid
Konten terpusatCentered container di dalam area isiPola: Centered Container

Karena area isi adalah elemen biasa, isi bebas memakai pola apa pun di dalamnya: container 960px untuk halaman pengaturan, grid kartu untuk statistik, atau layout artikel untuk laporan. Kerangka tidak peduli isinya — itulah nilai pola ini.

Demo berikut merakit shell lengkap. Gulir area isinya dan perhatikan sidebar dan header tetap diam:

Kesalahan Umum #

KesalahanAkibatnyaPerbaikannya
min-height: 0 terlewat pada area isiKonten panjang memaksa baris 1fr melebihi shell, halaman ikut menggulir utuhTambahkan min-height: 0 sebelum overflow-y: auto
Shell tanpa overflow: hiddenGulir halaman masih bisa terpicu oleh konten yang meluberKunci kerangka dengan overflow: hidden
Tinggi memakai 100vhBagian bawah kerangka tertutup address bar ponselGunakan 100dvh seperti yang dibahas di chapter Viewport Units
Sidebar diberi position: stickySticky tidak berperan karena halaman memang tidak pernah menggulirLepaskan sticky; sidebar yang diam adalah perilaku shell

Ringkasan #

Dashboard layout menukar strategi dari pola sidebar biasa: alih-alih halaman menggulir dengan sidebar sticky, kerangkanya dikunci setinggi viewport dan area isilah yang menggulir. overflow: hidden pada shell, overflow-y: auto plus min-height: 0 pada area isi adalah pasangan yang membuatnya bekerja. Setiap wilayahnya ternyata pola lama yang dipasang ulang — bukti bahwa section ini membangun satu kosakata layout yang menyambung. Pola berikutnya menutup halaman dari sisi sebaliknya: footer.