Saat membaca tabel panjang, kita ingin judul kolom tetap terlihat meski baris isinya terus bergulir. Saat membaca artikel dengan daftar isi, kita ingin ringkasan mengikuti sampai bagian selesai. Kebutuhan “menempel sementara” inilah yang dilayani oleh position bernilai sticky. Nilai ini adalah gabungan dua dunia: elemen berperilaku seperti relative di dalam alur, lalu berperilaku seperti fixed ketika ambang gulir tertentu tercapai. Pada Chapter ini kita membuat header tabel sticky dan menelaah syarat-syarat yang sering terlewat sehingga sticky tampak tidak bekerja.

Cara Kerja Sticky #

Elemen sticky selalu berangkat dari posisi normalnya di alur dokumen — ruangnya tetap disisakan, persis seperti relative. Ketika pengguna menggulir dan jarak elemen ke tepi kontainer gulir mencapai ambang yang dideklarasikan, misalnya top: 0, elemen berhenti mengikuti gulir dan tampak menempel. Perpindahan perilaku ini terjadi secara kontinu: satu piksel sebelum ambang, elemen masih relative; satu piksel setelahnya, elemen menempel.

Ada dua batasan yang membedakan sticky dari fixed. Pertama, acuannya adalah kontainer gulir terdekat (nearest scrolling ancestor), bukan viewport — pada halaman biasa kontainer itu adalah dokumen, tetapi di dalam kotak overflow: auto acuannya kotak tersebut. Kedua, elemen sticky tetap terkurung oleh parent-nya: menempel berhenti ketika tepi parent terlewati, sehingga elemen “terangkat” bersama bagian parent-nya yang bergulir keluar.

Contoh: Header Tabel yang Tetap Terlihat #

Demo chapter ini memuat dua eksperimen di dalam satu kontainer gulir setinggi 360px: tabel dengan header sticky dan kartu ringkasan yang menempel pada ambang 24px. Berikut CSS intinya:

css
.kontainer-tabel {
  height: 360px;
  overflow-y: auto;
}
thead th {
  position: sticky;
  top: 0;
}
.kartu-sticky {
  position: sticky;
  top: 24px;
}
html index.html
<div class="kontainer-tabel">
  <table>
    <thead>
      <tr><th>Barang</th><th>Stok</th></tr>
    </thead>
    <tbody><!-- dua belas baris isi --></tbody>
  </table>
  <div class="kartu-sticky">Ringkasan ikut menggulir lalu menempel.</div>
</div>

Hasil di Browser:

text
Kontainer gulir memiliki computed height: 360px dan overflow-y: auto.
Judul kolom tabel membawa position: sticky dengan top: 0px sehingga
tetap terlihat saat dua belas baris isi digulir di bawahnya. Kartu
ringkasan juga sticky dengan top: 24px: kartu mengikuti gulir, berhenti
24px dari tepi atas kontainer, lalu terangkat ketika parent-nya
terlewati.

Mari kita telaah aturan di atas baris demi baris:

  1. Baris 2–3 (height: 360px + overflow-y: auto): kotak ini menjadi kontainer gulir — acuan bagi semua keturunan sticky di dalamnya.
  2. Baris 5–6 (position: sticky pada thead th): header tabel dicalonkan untuk menempel. Selector menarget th, bukan thead, karena elemen yang di-attach harus kotak yang dirender.
  3. Baris 7 (top: 0): ambangnya — header menempel setelah tepi atasnya mencapai tepi atas kontainer. Tanpa baris ini tidak ada perilaku menempel.
  4. Baris 9–10 (kartu ringkasan): ambang top: 24px menempatkan kartu 24px di bawah tepi kontainer saat menempel, berguna agar tidak menempel persis di tepi.

Syarat yang Sering Terlewat #

Selain inset, sticky mensyaratkan ruang untuk menempel. Bila parent setinggi kontennya sendiri, tidak ada sisa ruang di dalam parent yang bisa dilalui, sehingga elemen tidak pernah sempat menempel — kasus klasiknya sticky di dalam sel tabel atau kartu yang tingginya pas. Pastikan parent lebih tinggi daripada elemen sticky dan kontainer gulir lebih tinggi daripada parent.

Jebakan kedua menyangkut rantai ancestor. Setiap ancestor dengan overflow selain visible menjadi kontainer gulir tersendiri. Kotak dengan overflow-x: auto yang terlihat “aman” pun mengubah acuan sticky: elemen menempel terhadap kotak itu, bukan terhadap halaman, dan karena kotak itu sendiri tidak pernah digulir secara vertikal, sticky tampak mati total. Dokumentasi position di MDN merinci perilaku sticky bersama kontainer gulir untuk kasus-kasus lanjutan.