← semua materi
15:00 Teknis · 18 Oct 2026 · 15:01

📚 CSS Layout Modern: Flexbox vs Grid — dan Kenapa float Mati

Level: Dasar · Konteks: Frontend · Status data: sebagian diverifikasi web (Oktober 2026)


🎯 Tujuan Belajar

  1. Paham model mental yang membedakan flexbox dan grid — bukan hafal properti.
  2. Bisa memilih axis yang benar sebelum menulis satu baris CSS.
  3. Tahu kenapa float bukan alat layout lagi (dan kenapa masih ketemu di codebase lama).
  4. Kenal state terkini masonry/grid-lanes per Oktober 2026.

🏗️ Arsitektur & Alur Teknis

Akar masalah: normal flow itu satu dimensi

Browser menata elemen block secara vertikal bertumpuk, inline secara horizontal. Semua layout CSS modern adalah cara meng-override normal flow secara terbatas dan deklaratif.

Evolusi tiga generasi:

Era Teknik Mekanisme Masalah
~2000-an float + clearfix Elemen dikeluarkan dari normal flow, teks membungkusnya Bukan layout engine; butuh hack clearfix, tinggi container kolaps, urutan DOM ≠ visual
2009+ Flexbox Distribusi ruang di satu axis Tidak bisa kontrol baris & kolom sekaligus
2017+ Grid Track 2D eksplisit, baris dan kolom Overkill untuk aliran satu dimensi
2023+ Container queries, subgrid Layout responsif berbasis ukuran parent, bukan viewport —
2026 grid-lanes (masonry) Track lanes dengan item mengisi celah Dukungan browser belum merata

Kenapa float "mati"

float dirancang untuk membungkus teks di sekitar gambar, bukan untuk menyusun kolom. Yang membuatnya dipakai sebagai layout adalah ketiadaan alternatif. Warisan masalahnya:

  1. Container tidak mengukur anak yang di-float → tinggi kolaps → butuh overflow: hidden atau pseudo-element clearfix.
  2. float adalah properti flow, bukan properti layout — tidak ada konsep distribusi ruang, alignment, atau gap.
  3. Urutan visual terlepas dari urutan DOM → aksesibilitas & tab order rusak.
  4. Tidak ada cara bersih membuat kolom sama tinggi sebelum flexbox.

Kesimpulan: float masih sah untuk maksud aslinya (gambar dalam artikel). Untuk layout, sudah digantikan sepenuhnya.


💻 Kode: Memilih Axis

Aturan pemilihan (satu pertanyaan)

Apakah saya perlu mengontrol baris DAN kolom sekaligus? Tidak → Flexbox. Ya → Grid.

/* Flexbox: navbar — satu axis, distribusi ruang */
.nav {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.nav__logo { margin-inline-end: auto; } /* dorong sisa item ke kanan */
/* Grid: dashboard — dua axis, alignment eksplisit */
.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "sidebar header"
    "sidebar main"
    "sidebar footer";
  min-height: 100dvh;
  gap: 1rem;
}
.dashboard > header { grid-area: header; }
/* Grid + auto-fit: card list responsif tanpa media query */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 1rem;
}

minmax(min(280px, 100%), 1fr) — trik penting: mencegah overflow di viewport < 280px. Tanpa min(), minmax(280px, 1fr) bikin horizontal scroll di layar kecil.

flex-basis vs width — sumber bug klasik

.item { flex: 1 1 0%; }   /* tumbuh dari nol — kolom benar-benar sama lebar */
.item { flex: 1 1 auto; } /* tumbuh dari konten — kolom lebar ikut isi */

flex: 1 = shorthand untuk 1 1 0%. Kalau konten panjang bikin kolom tidak rata, biasanya karena auto.

min-width: auto pada flex item

Default min-width flex item adalah auto, artinya item tidak boleh menyusut di bawah ukuran konten minimumnya. Ini penyebab utama overflow pada flex row yang berisi teks panjang atau <pre>:

.flex-child {
  min-width: 0;        /* atau overflow: hidden */
  /* tanpa ini: teks panjang memaksa container melebar */
}

Grid punya masalah serupa di track 1fr → solusinya minmax(0, 1fr).


⚖️ Trade-off & Pendekatan Alternatif

Aspek Flexbox Grid
Dimensi 1D (satu axis utama) 2D (baris + kolom)
Ukuran track Ditentukan konten & flex-grow Ditentukan author via fr, minmax, auto
Alignment Per-item, sepanjang axis Per-item & per-track
Responsif Butuh flex-wrap + media query auto-fit/auto-fill tanpa media query
Learning curve Rendah Sedang (banyak properti, konsep track)
Overhead Ringan Sedikit lebih berat di kasus ekstrem (ratusan item)
Kasus terbaik Navbar, toolbar, tombol+ikon, form inline Page layout, dashboard, galeri, tabel
Kasus salah pakai Layout halaman 2D dipaksa Baris tombol sederhana (overkill)

Pendekatan alternatif yang sudah tidak relevan: float layout, display: table layout, absolute positioning untuk kolom. Semuanya menangani gejala, bukan model.

Status masonry — DIVERIFIKASI, Oktober 2026

Proposal masonry diselesaikan sebagai display: grid-lanes (sebelumnya disebut "CSS Grid Lanes"), menggantikan proposal lama grid-template-rows: masonry.

Pola progressive enhancement yang aman:

.masonry {
  display: grid;
  display: grid-lanes;               /* fallback ke grid biasa bila tak didukung */
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
}

Browser tanpa dukungan mengabaikan deklarasi kedua dan tetap menampilkan grid rapi. Jangan pakai flow-tolerance: infinite — itu mengubah urutan visual dan merusak reading-flow.

⚠️ Catatan: angka versi Safari 26.4 berasal dari MDN compat table & blog teknis, bukan benchmark independen. Status Chrome/Firefox bisa berubah cepat — cek caniuse sebelum dipakai produksi.


🏭 Use Case Produksi & Failure Mode Umum

Failure mode yang paling sering ditemui di code review:

  1. Flex row + teks panjang → overflow horizontal. Fix: min-width: 0 pada child.
  2. height: 100% pada child flex/grid tidak bekerja. Persentase butuh parent dengan tinggi pasti. Fix: flex: 1 + min-height: 0, atau align-items: stretch (default).
  3. Nested flex tanpa min-height: 0 → scroll container tidak pernah scroll karena anak mendorong tinggi parent. Ini bug klasik pada layout "header + scrollable body".
  4. gap pada flex wrap aman di semua browser modern, tapi gap pada flex column sempat buggy di Safari lama. Sekarang aman.
  5. Grid 1fr melebar karena konten → gunakan minmax(0, 1fr).
  6. justify-content vs justify-items tertukar. justify-content mengatur track/ruang antar item; justify-items mengatur item di dalam cell.
  7. order dipakai untuk mengubah urutan visual → tab order tetap ikut DOM. Aksesibilitas rusak. Hindari di luar kasus kosmetik.
  8. float layout lama yang di-"modernisasi" setengah jalan — float dihapus tapi clearfix ditinggal. Sisa teknis, bukan bug, tapi indikator codebase belum dimigrasi.

Pola produksi yang terbukti:

.card-wrapper { container-type: inline-size; }

@container (min-width: 400px) {
  .card { grid-template-columns: 120px 1fr; }
}

🛠️ Latihan Praktis Kecil

Target: 30 menit, satu file HTML.

Bangun layout "app shell" dengan requirement:

  1. Sidebar 240px fixed, main area fleksibel, min-height: 100dvh.
  2. Header di atas main, tidak mencakup sidebar.
  3. Main area punya daftar card responsif: minimum 260px per card, mengisi lebar otomatis tanpa media query.
  4. Di dalam setiap card: ikon + judul dalam satu baris, judul boleh terpotong ellipsis.
  5. Sidebar harus scroll sendiri bila isinya panjang; header tetap terlihat.

Petunjuk: butuh Grid untuk shell, Grid lagi untuk cards, Flexbox untuk baris ikon+judul, dan min-width: 0 di suatu tempat. Kalau ada horizontal scrollbar, kamu melewatkan satu dari empat hal itu.

Verifikasi: resize viewport ke 320px. Tidak boleh ada scroll horizontal.


✅ Cek Pemahaman

  1. Kenapa flex: 1 dan flex: 1 1 auto menghasilkan lebar kolom berbeda saat isi kontennya beda panjang? Properti mana yang jadi penyebab?
  2. Kamu punya container yang harus scroll vertikal di dalam layout flex column, tapi malah seluruh halaman yang scroll. Apa penyebabnya dan apa fix satu barisnya?
  3. Kapan kamu sengaja memilih Grid untuk sesuatu yang sebenarnya bisa diselesaikan Flexbox — dan apa alasannya?

🔑 Poin Kunci


➡️ Eksplorasi Lanjut

  1. subgrid — kenapa ini menyelesaikan masalah alignment lintas level nesting yang tidak bisa diselesaikan Grid biasa.
  2. Container queries — pergeseran paradigma dari "viewport-responsive" ke "component-responsive"; ini perubahan arsitektur CSS yang lebih besar dari flexbox→grid.
  3. reading-flow & reading-order — spesifikasi aksesibilitas yang lahir dari masalah masonry; kenapa urutan visual dan urutan DOM akhirnya dipertemukan.
  4. Layout performance — kapan Grid mahal, dan kenapa contain: layout bisa menyelamatkan frame time di list panjang.
  5. Logical properties (margin-inline, padding-block) — migrasi dari fisik ke logis untuk dukungan RTL tanpa duplikasi CSS.