Pada halaman yang isinya pendek — halaman masuk, konfirmasi, atau dokumen dua paragraf — footer sering “mengapung” di tengah layar karena browser hanya menempatkannya setelah konten selesai. Kita ingin perilaku sebaliknya: bila konten kurang tinggi, footer tetap menempel di dasar viewport; bila konten lebih tinggi dari viewport, footer mengikuti sampai ujung halaman seperti biasa. Resep flexbox tiga deklarasi berikut menyelesaikan kedua kondisi itu sekaligus.

Resep ini menata <body> sebagai kolom flex setinggi minimal viewport, lalu memberi seluruh sisa ruang vertikal kepada area konten:

css
body {
  min-height: 100vh;   /* fallback untuk browser tanpa dvh */
  min-height: 100dvh;  /* tinggi viewport dinamis */
  display: flex;
  flex-direction: column;
}
main { flex: 1; }

Struktur halaman mengikuti urutan tiga bagian standar:

html index.html
<body>
  <header>
    <strong>Aplikasi Catatan</strong>
  </header>
  <main>
    <h1>Selamat datang kembali</h1>
    <p>Konten halaman ini sengaja pendek.</p>
  </main>
  <footer>
    <p>© 2026 Aplikasi Catatan</p>
  </footer>
</body>

Hasil di Browser:

text
Pada viewport 1280x720 dengan konten pendek: computed body
min-height 720px (100dvh), display flex, flex-direction column.
Area main membawa flex-grow 1 sehingga melar menyerapi seluruh
sisa ruang vertikal — footer berada tepat di dasar viewport.

Mari kita telaah cara kerja tiap deklarasi:

  1. min-height: 100dvh: tubuh halaman diberi tinggi minimal setinggi viewport, sehingga footer punya “lantai” untuk didorong ke bawah. Satuan dvh menyesuaikan tinggi saat URL bar ponsel muncul atau menyusut; 100vh di baris sebelumnya adalah fallback untuk browser yang belum mendukungnya (lihat viewport-units ).
  2. display: flex; flex-direction: column: header, main, dan footer menjadi item flex yang tersusun vertikal, satu per baris.
  3. flex: 1 pada main: singkatan dari flex-grow: 1; flex-shrink: 1; flex-basis: 0% — area konten mengambil seluruh ruang sisa setelah tinggi header dan footer diperhitungkan (lihat flex-grow-shrink-basis ).

Ketika konten lebih panjang dari viewport, min-height tidak lagi berperan; body tumbuh mengikuti konten dan footer duduk natural di bagian paling bawah dokumen. Satu resep, dua kondisi, tanpa media query.

Resep ini gagal dengan cara yang khas bila diterapkan pada elemen yang salah. min-height: 100dvh harus diberikan pada pembungkus yang memuat ketiga bagian — <body> atau satu div pembungkus paling luar. Memberikannya pada <main> justru membuat area konten sendiri setinggi viewport, sehingga footer terdorong di bawah lipatan. Kesalahan kedua: menaruh flex: 1 pada header atau footer — kedua bagian itu justru harus setinggi kontennya; hanya area tengah yang boleh melar. Terakhir, hindari position: fixed sebagai jalan pintas: footer fixed menutupi akhir konten dan tidak terdorong saat halaman lebih panjang dari viewport.

Alternatif: margin-top: auto dan Grid #

Dua resep lain menghasilkan perilaku yang sama. Yang pertama menyerahkan pemenggalan ruang kepada margin auto pada footer, sehingga main tidak perlu disentuh:

css
body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
footer { margin-top: auto; }

Sisa ruang vertikal diserap margin atas footer, bukan oleh main. Pola ini berguna bila struktur halaman punya elemen lain di antara konten dan footer yang tidak ingin diubah perilakunya. Versi ketiga memakai grid dengan pola baris auto 1fr auto:

css
body {
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

Baris pertama dan ketiga setinggi kontennya (auto), baris tengah menyerap sisa ruang (1fr). Ketiga resep sama validnya — pilih satu dan gunakan konsisten, karena mencampurnya pada halaman yang sama membuat alasan setiap deklarasi sulit dilacak.

Cara tercepat menguji resep ini: buka DevTools, aktifkan mode responsif, lalu geser tinggi viewport. Footer harus tetap menempel di dasar pada setiap tinggi ketika konten pendek, dan tetap mengikuti alur dokumen ketika konten melebihi viewport.

Demo chapter ini memuat penanda uji otomatis yang memverifikasi min-height 720px, display: flex, flex-direction: column pada body, serta flex-grow: 1 dan flex-basis: 0% pada area konten utama.