📚 CSS Layout Modern: Flexbox vs Grid — dan Kenapa float Mati
Level: Dasar · Konteks: Frontend · Status data: sebagian diverifikasi web (Oktober 2026)
🎯 Tujuan Belajar
- Paham model mental yang membedakan flexbox dan grid — bukan hafal properti.
- Bisa memilih axis yang benar sebelum menulis satu baris CSS.
- Tahu kenapa
floatbukan alat layout lagi (dan kenapa masih ketemu di codebase lama). - Kenal state terkini masonry/
grid-lanesper 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:
- Container tidak mengukur anak yang di-float → tinggi kolaps → butuh
overflow: hiddenatau pseudo-element clearfix. floatadalah properti flow, bukan properti layout — tidak ada konsep distribusi ruang, alignment, atau gap.- Urutan visual terlepas dari urutan DOM → aksesibilitas & tab order rusak.
- 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.
- Safari 26.4 — shipped
grid-lanes, full support (desktop + iOS). - Chrome/Edge — belum stable; tersedia di belakang flag
CSS Grid Lanes Layout. - Firefox — belum support.
reading-flow— Chrome mendahulukan ini; Safari belum support. Ini masalah aksesibilitas: urutan visual masonry ≠ urutan DOM.
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:
- Flex row + teks panjang → overflow horizontal. Fix:
min-width: 0pada child. height: 100%pada child flex/grid tidak bekerja. Persentase butuh parent dengan tinggi pasti. Fix:flex: 1+min-height: 0, ataualign-items: stretch(default).- Nested flex tanpa
min-height: 0→ scroll container tidak pernah scroll karena anak mendorong tinggi parent. Ini bug klasik pada layout "header + scrollable body". gappada flex wrap aman di semua browser modern, tapigappada flex column sempat buggy di Safari lama. Sekarang aman.- Grid
1frmelebar karena konten → gunakanminmax(0, 1fr). justify-contentvsjustify-itemstertukar.justify-contentmengatur track/ruang antar item;justify-itemsmengatur item di dalam cell.orderdipakai untuk mengubah urutan visual → tab order tetap ikut DOM. Aksesibilitas rusak. Hindari di luar kasus kosmetik.floatlayout lama yang di-"modernisasi" setengah jalan —floatdihapus tapiclearfixditinggal. Sisa teknis, bukan bug, tapi indikator codebase belum dimigrasi.
Pola produksi yang terbukti:
- Grid untuk page shell, flex untuk komponen di dalamnya. Ini konvensi dominan di design system modern (mis. pola internal dashboard). Grid mendefinisikan wilayah, flex mengatur isi wilayah.
grid-template-areasuntuk layout halaman — lebih mudah dibaca daripada angka line number, dan bisa di-redefinisi total dalam satu media query.- Container queries untuk komponen reusable — komponen harus responsif terhadap lebar container, bukan viewport, karena komponen yang sama bisa muncul di sidebar sempit dan main area lebar.
.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:
- Sidebar 240px fixed, main area fleksibel,
min-height: 100dvh. - Header di atas main, tidak mencakup sidebar.
- Main area punya daftar card responsif: minimum 260px per card, mengisi lebar otomatis tanpa media query.
- Di dalam setiap card: ikon + judul dalam satu baris, judul boleh terpotong ellipsis.
- 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
- Kenapa
flex: 1danflex: 1 1 automenghasilkan lebar kolom berbeda saat isi kontennya beda panjang? Properti mana yang jadi penyebab? - 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?
- Kapan kamu sengaja memilih Grid untuk sesuatu yang sebenarnya bisa diselesaikan Flexbox — dan apa alasannya?
🔑 Poin Kunci
- Flexbox = 1D, Grid = 2D. Pilih axis dulu, properti belakangan.
floatbukan layout tool. Mati bukan karena deprecated, tapi karena salah alat sejak awal.min-width: 0/minmax(0, 1fr)adalah dua baris CSS yang menyelesaikan mayoritas bug overflow.auto-fit+minmax(min(...), 1fr)menghapus kebutuhan media query untuk grid card.- Masonry masih belum siap produksi lintas browser (Okt 2026): Safari 26.4 yes, Chrome flag-only, Firefox no. Pakai progressive enhancement, jangan andalkan.
- Grid untuk shell, flex untuk komponen — konvensi yang paling tidak banyak drama.
➡️ Eksplorasi Lanjut
subgrid— kenapa ini menyelesaikan masalah alignment lintas level nesting yang tidak bisa diselesaikan Grid biasa.- Container queries — pergeseran paradigma dari "viewport-responsive" ke "component-responsive"; ini perubahan arsitektur CSS yang lebih besar dari flexbox→grid.
reading-flow&reading-order— spesifikasi aksesibilitas yang lahir dari masalah masonry; kenapa urutan visual dan urutan DOM akhirnya dipertemukan.- Layout performance — kapan Grid mahal, dan kenapa
contain: layoutbisa menyelamatkan frame time di list panjang. - Logical properties (
margin-inline,padding-block) — migrasi dari fisik ke logis untuk dukungan RTL tanpa duplikasi CSS.