Laptop menampilkan halaman web dengan navigasi yang menempel di bagian atas layar

Sticky header adalah bilah navigasi yang menempel di atas layar ketika pengunjung menggulir halaman. Kamu bisa membuatnya hanya dengan CSS position: sticky tanpa library tambahan. JavaScript baru dibutuhkan kalau header perlu berubah tampilan, misalnya mengecil atau menambah bayangan saat halaman sudah tergulir.

Membuat sticky header dengan CSS position

Struktur HTML-nya sederhana. Satu elemen header berisi navigasi, lalu konten utama di bawahnya.

<header class="site-header">
  <nav class="nav">
    <a href="/">Beranda</a>
    <a href="/artikel/">Artikel</a>
    <a href="/kontak/">Kontak</a>
  </nav>
</header>
<main>...</main>

Tambahkan aturan berikut pada elemen header. top: 0 menentukan jarak tempel dari tepi atas viewport, sedangkan z-index memastikan header tidak tertutup elemen lain.

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #fff;
}

Supaya sticky bekerja, elemen induk tidak boleh punya overflow: hidden atau overflow: auto. Properti itu memotong area scroll dan membuat header ikut hilang bersama induknya. Kalau header tidak menempel sama sekali, periksa dulu properti overflow pada body, html, atau pembungkus di atasnya.

Menangani tinggi header agar konten tidak tertutup

Header sticky tetap memakan ruang di alur dokumen selama belum menempel, jadi konten di bawahnya tidak akan tertutup dari awal. Masalah muncul ketika kamu memakai anchor link seperti #bagian-2. Browser menggulir tepat ke elemen tujuan, dan bagian atas elemen itu tertutup header.

Solusinya scroll-margin-top pada elemen tujuan. Nilainya kira-kira setinggi header ditambah sedikit ruang napas.

h2[id], section[id] {
  scroll-margin-top: 80px;
}

Kalau tinggi header berubah antar breakpoint, sesuaikan nilai ini di media query yang sama. Menetapkan tinggi header secara eksplisit lewat variabel CSS membuat perawatan lebih mudah karena satu angka dipakai di beberapa tempat.

:root {
  --header-height: 64px;
}

.site-header {
  min-height: var(--header-height);
}

h2[id], section[id] {
  scroll-margin-top: calc(var(--header-height) + 16px);
}

Menambahkan efek saat halaman digulir

Header yang menempel di atas konten putih sering menyatu dan sulit dibedakan. Tambahkan bayangan atau garis bawah ketika pengguna sudah menggulir melewati ambang tertentu. Perubahan ini butuh JavaScript karena CSS belum punya cara membaca posisi scroll secara langsung untuk keperluan ini.

const header = document.querySelector('.site-header');
const ambang = 10;

function perbaruiHeader() {
  header.classList.toggle('is-scrolled', window.scrollY > ambang);
}

window.addEventListener('scroll', perbaruiHeader, { passive: true });
perbaruiHeader();

Opsi { passive: true } memberi tahu browser bahwa listener tidak akan memanggil preventDefault(), sehingga scroll tetap lancar di perangkat sentuh. Aturan CSS untuk kelas tambahannya cukup singkat.

.site-header.is-scrolled {
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}

Fungsi perbaruiHeader() dipanggil sekali di awal untuk menangani kasus halaman dimuat dalam keadaan sudah tergulir, misalnya saat pengguna me-refresh di tengah halaman.

Membatasi pemanggilan dengan requestAnimationFrame

Event scroll bisa terpicu puluhan kali per detik. Membungkus pembaruan kelas di dalam requestAnimationFrame membuat perubahan hanya terjadi sekali per frame render.

let menunggu = false;

window.addEventListener('scroll', () => {
  if (menunggu) return;
  menunggu = true;
  requestAnimationFrame(() => {
    perbaruiHeader();
    menunggu = false;
  });
}, { passive: true });

Untuk header sederhana, perbedaan performanya kecil, tapi pola ini berguna kalau nanti kamu menambahkan animasi ukuran atau menghitung posisi elemen lain di dalam handler yang sama.

Menyesuaikan header dengan breakpoint

Di layar sempit, header biasanya lebih tinggi karena menu berubah menjadi tombol atau bertumpuk. Karena itu nilai --header-height perlu diubah di media query, bukan ditulis ulang di banyak tempat.

@media (max-width: 640px) {
  :root {
    --header-height: 56px;
  }
}

Kalau navigasi di dalam header memakai flexbox untuk mengatur jarak antarmenu, teknik dasar di tutorial CSS Flexbox untuk layout web bisa langsung dipakai. Untuk halaman yang lebih kompleks, misalnya header dengan dua baris dan sidebar, layout responsive dengan CSS Grid memberi kontrol lebih rapi terhadap area header dibanding flexbox saja.

Menangani elemen yang menutupi header

Lightbox, modal, atau tooltip biasanya memakai position: fixed dengan z-index tinggi. Kalau elemen itu muncul dan menutupi header, periksa urutan z-index di seluruh halaman. Satukan nilainya dalam variabel agar tidak ada dua elemen yang berebut angka sama.

:root {
  --z-header: 100;
  --z-modal: 200;
  --z-tooltip: 300;
}

Menumpuk position: sticky dengan elemen berposisi lain di dalam satu kontainer bisa membingungkan. Kalau header berada di dalam pembungkus yang juga punya position dan z-index, konteks tumpukannya baru, dan header tidak lagi dibandingkan langsung dengan elemen di luar pembungkus. Materi cara mengatur posisi elemen dengan CSS position membahas perilaku ini lebih rinci.

Menguji header di berbagai kondisi

Beberapa hal yang perlu dicek sebelum kode dianggap selesai:

  • Gulir halaman dengan keyboard (tombol Page Down dan End) dan pastikan header tetap menempel.
  • Klik anchor link menuju subjudul dan pastikan judul tidak tertutup header.
  • Putar layar ponsel dari potret ke lanskap, lalu periksa tinggi header tidak berubah di tengah jalan.
  • Matikan JavaScript dan pastikan header masih menempel, hanya tanpa efek bayangan.

Untuk memeriksa apakah halaman bisa dijangkau dari lokasi pengguna, alat seperti cek ping situs dari berbagai lokasi berguna ketika kamu menduga masalahnya bukan di kode header, melainkan di jaringan atau DNS. Kalau pengujian membutuhkan koneksi tanpa gangguan notifikasi dan pelacakan, situs panduan fokus saat menguji di browser bisa jadi acuan untuk menyiapkan lingkungan kerja yang lebih tenang.

Browser lama yang tidak mendukung position: sticky akan menampilkan header biasa yang ikut tergulir. Perilaku ini aman sebagai cadangan. Kalau tetap ingin header menempel di browser tersebut, gunakan @supports untuk mendeteksi dukungan dan berikan position: fixed beserta padding-top pada body sebagai gantinya.

@supports not (position: sticky) {
  .site-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
  }
  body {
    padding-top: var(--header-height);
  }
}

Header sticky yang baik tidak menarik perhatian pada dirinya sendiri. Ia hanya memastikan navigasi selalu dalam jangkauan, dengan tinggi yang tidak berubah-ubah dan efek visual yang cukup untuk memisahkannya dari konten.

Pertanyaan yang Sering Diajukan

Kenapa position sticky tidak berfungsi di header saya?

Penyebab paling umum adalah elemen induk yang punya overflow: hidden, overflow: auto, atau overflow: scroll. Selain itu, pastikan kamu menulis top (misalnya top: 0), karena tanpa properti itu elemen sticky tidak punya titik tempel. Periksa juga apakah ada height tetap pada induk yang membuat area scroll-nya habis sebelum header sempat menempel.

Apakah sticky header mengganggu aksesibilitas?

Header yang terlalu tinggi bisa menghabiskan ruang layar di ponsel dan menyulitkan pembaca dengan pembesaran teks. Jaga tingginya serendah mungkin, dan pastikan tautan di dalamnya tetap bisa difokus dengan keyboard. Jika header memuat animasi mengecil, sediakan opsi untuk mematikannya lewat media query prefers-reduced-motion.

Perlukah library JavaScript untuk sticky header?

Tidak. CSS position: sticky sudah menangani perilaku menempel, dan JavaScript hanya diperlukan untuk perubahan tampilan berbasis posisi scroll. Menambahkan library untuk kebutuhan ini menambah ukuran halaman tanpa manfaat yang sepadan.

Related Posts