Piksel memberi presisi, tetapi layout yang baik harus menyesuaikan diri dengan lebar layar yang tidak kita kendalikan. Satuan fr (fraction) dibuat khusus untuk kebutuhan itu dan hanya tersedia di dalam Grid: ia membagi ruang bebas container ke setiap track sesuai porsinya. Chapter ini membahas cara kerja fr, perbandingannya dengan persen, serta satu jebakan klasik — nilai 1fr yang menolak menyusut ketika kontennya panjang — bersama solusi resminya.
fr Membagi Ruang Bebas, Bukan Lebar Penuh #
Definisi yang wajib melekat: 1fr adalah satu bagian dari ruang bebas container setelah track berukuran tetap dan gap dihitung lebih dulu. Nilai 1fr 2fr bukan berarti “sepertiga dan dua pertiga container”, melainkan “1 bagian dan 2 bagian dari sisa ruang”.
.dua-panel {
display: grid;
grid-template-columns: 200px 1fr;
gap: 16px;
}Mari kita telaah perilakunya pada container selebar 500 piksel:
200pxdipotong lebih dulu dari lebar container; track ini tidak pernah berubah.gap: 16pxjuga dipotong sebelum pembagian; ruang antar track dijaga tetap.- Sisa ruang bebas = 500 − 200 − 16 = 284 piksel.
1frmenerima seluruh sisa tersebut: 284 piksel. Saat container melebar menjadi 800 piksel, hanya trackfryang ikut membesar (584 piksel), sementara kolom tetap diam di 200 piksel.
Proporsi fr bekerja dengan prinsip yang sama. Pada container 500 piksel dengan gap: 16px, deklarasi grid-template-columns: 1fr 2fr membagi 484 piksel menjadi tiga bagian: kolom kiri sekitar 161 piksel dan kolom kanan sekitar 323 piksel.
Demo berikut menampilkan dua grid: yang pertama memadukan track tetap dengan fr, yang kedua murni proporsional:
Inilah perbedaan mendasar dari piksel: yang kita definisikan adalah perbandingan, bukan angka pasti — panel kanan selalu dua kali lebar panel kiri, pada layar ponsel maupun monitor lebar. Geser lebar jendela demo dan hanya panel fr yang berubah.
fr versus Persen #
Sekilas 1fr mirip 100% dibagi rata, tetapi keduanya berbeda pada dua hal penting:
| Aspek | fr | % |
|---|---|---|
| Perhitungan | Dibagi dari ruang bebas setelah gap | Persentase lebar container, gap dihitung terpisah |
| Tiga kolom + 2 gap | 1fr 1fr 1fr selalu pas, tidak meluap | Tiga 33% + gap memicu overflow mendatar |
| Merespons konten | Membaca minimum konten (lihat jebakan di bawah) | Tidak memedulikan konten |
Kasus tiga kolom memperlihatkan keunggulannya dengan jelas: grid-template-columns: 33% 33% 33% bersama gap: 16px menghasilkan total 99% ditambah dua gap, sehingga grid melebihi container. Deklarasi 1fr 1fr 1fr memotong gap lebih dulu, lalu membagi sisanya — hasilnya selalu muat persis.
Jebakan: 1fr Menolak Menyusut #
Secara spesifikasi, 1fr sebenarnya adalah singkatan dari minmax(auto, 1fr) — pembahasan fungsi minmax() menyusul dua chapter lagi. Bagian auto di situ berarti ukuran minimum track mengikuti konten, bukan nol. Akibatnya satu kata panjang tanpa spasi — URL, nomor transaksi, nama berkas — memaksa track melebar melebihi bagiannya, dan kolom yang seharusnya sama lebar menjadi timpang.
Perbaikannya adalah menurunkan minimum itu ke nol:
.kolom-sama {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}Dengan minimum 0, kedua track menerima bagiannya dengan patuh, dan konten panjang akan terpotong atau di-wrap sesuai pengaturan kita — bukan mendistorsi grid. Resep ini begitu sering dipakai pada layout aplikasi hingga layak dihafal; kita membedahnya lebih dalam pada chapter Fungsi minmax().
Ringkasan #
Satuan fr mendefinisikan proporsi atas ruang bebas: track tetap dan gap dipotong lebih dulu, sisanya dibagikan sesuai bobot masing-masing track. Karena menghitung gap di dalam pembagiannya, fr menghindari overflow yang sering terjadi pada kombinasi persen, dan membuat layout tahan terhadap perubahan lebar layar. Ingat pula sisi halusnya: 1fr membawa minimum auto dari konten, dan minmax(0, 1fr) adalah kunci untuk mengendalikannya. Setelah menguasai fr, daftar track panjang seperti 1fr 1fr 1fr 1fr terasa repetitif — chapter berikutnya memperkenalkan fungsi repeat() untuk menuliskannya ringkas.