ngodingdulu
Web & DatabaseTutorialPemula

Flexbox dan Grid CSS: Layout Modern untuk Pemula

Dua alat layout yang menggantikan trik-trik lama seperti float. Kamu akan memakai keduanya untuk membuat satu halaman responsif dari nol.

Oleh Afa Hernandes14 menit baca

Daftar isi

Dulu, membuat layout dengan CSS penuh trik: float, clearfix, tabel, atau angka margin yang dihitung manual dan rusak begitu ukuran layar berubah. Sekarang ada dua alat yang memang dibuat untuk layout: Flexbox dan Grid. Keduanya didukung semua browser modern, jadi kamu bisa langsung memakainya.

Di tutorial ini kamu akan membuat halaman sederhana untuk sebuah kedai kopi: header dengan menu, bagian pembuka di tengah layar, deretan kartu menu, dan bagian lokasi. Halamannya otomatis menyesuaikan diri: empat kolom di laptop, satu kolom di HP.

Sebelum mulai

  • Editor kode, misalnya VS Code. Cara menyiapkannya ada di tutorial VS Code dan terminal.
  • Browser modern. Contoh di tutorial ini diuji di Chrome.
  • Tahu sedikit HTML (tag, atribut, class). Kalau belum, baca dulu bagian “Cara kerja web” di roadmap web developer.

Buat folder kopi-senja berisi dua file kosong: index.html dan style.css.

Langkah 1: Tulis struktur HTML

Mulai dari isinya dulu, tampilannya belakangan. Pakai tag yang sesuai maknanya: header untuk kepala halaman, nav untuk menu, main untuk isi utama, section untuk tiap bagian, article untuk tiap kartu, dan footer untuk kaki halaman. Tag seperti ini disebut HTML semantik. Pembaca layar (screen reader) dan mesin pencari jadi lebih mudah memahami halamanmu.

kopi-senja/index.html
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Kedai Kopi Senja</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="site-header">
<a class="logo" href="#">Kopi Senja</a>
<nav>
<ul class="nav-list">
<li><a href="#menu">Menu</a></li>
<li><a href="#lokasi">Lokasi</a></li>
<li><a href="#kontak">Kontak</a></li>
</ul>
</nav>
</header>
<main>
<section class="hero">
<h1>Kopi enak, harga teman.</h1>
<p>Diseduh setiap pagi dari biji kopi lokal.</p>
<a class="button" href="#menu">Lihat menu</a>
</section>
<section id="menu" class="menu">
<h2>Menu favorit</h2>
<div class="card-grid">
<article class="card">
<h3>Kopi susu</h3>
<p>Espresso, susu segar, gula aren.</p>
<p class="price">Rp18.000</p>
</article>
<article class="card">
<h3>Americano</h3>
<p>Espresso dan air panas, tanpa gula.</p>
<p class="price">Rp15.000</p>
</article>
<article class="card">
<h3>Matcha latte</h3>
<p>Matcha Jepang dengan susu segar, bisa panas atau dingin.</p>
<p class="price">Rp22.000</p>
</article>
<article class="card">
<h3>Croissant</h3>
<p>Dipanggang setiap pagi, renyah di luar.</p>
<p class="price">Rp25.000</p>
</article>
</div>
</section>
<section id="lokasi" class="lokasi">
<div>
<h2>Lokasi</h2>
<p>Jl. Contoh No. 12, dekat kampus. Parkir motor tersedia.</p>
</div>
<div id="kontak">
<h2>Kontak</h2>
<p>Pesan antar lewat WhatsApp kedai, setiap hari sampai pukul 21.00.</p>
</div>
</section>
</main>
<footer class="site-footer">
<p>Buka setiap hari, 07.00–22.00</p>
</footer>
</body>
</html>

Perhatikan baris <meta name="viewport" …>. Tanpa baris ini, browser HP menganggap halamanmu dibuat untuk layar lebar lalu mengecilkannya, sehingga tulisannya jadi kecil sekali. Baris ini wajib ada di setiap halaman yang ingin tampil baik di HP.

Buka index.html di browser. Isinya sudah tampil, tapi masih polos dan bertumpuk ke bawah. Itu normal: kita belum menulis CSS apa pun.

Langkah 2: Pasang dasar CSS

kopi-senja/style.css
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: #1f2328;
background: #fbf9f6;
}

box-sizing: border-box membuat width sebuah elemen sudah termasuk padding dan border-nya. Tanpa ini, kotak selebar 300px dengan padding 20px sebenarnya jadi 340px, dan layout mudah meleber. Hampir semua proyek modern memasang aturan ini di awal.

Flexbox: menyusun elemen dalam satu arah

Flexbox dipakai untuk menyusun elemen dalam satu baris atau satu kolom. Kamu memasang display: flex di elemen pembungkus (disebut flex container), lalu anak-anaknya (flex item) otomatis berjajar.

Ada dua sumbu yang perlu dipahami:

Properti Mengatur Nilai yang sering dipakai
flex-direction arah susunan row (bawaan, mendatar), column (menurun)
justify-content posisi di sumbu utama (searah flex-direction) flex-start, center, space-between
align-items posisi di sumbu silang (tegak lurus sumbu utama) stretch (bawaan), center, flex-start
gap jarak antar-item 1rem, 20px
flex-wrap boleh pindah baris kalau tidak muat wrap

Kalau flex-direction: row, sumbu utamanya mendatar, jadi justify-content mengatur posisi kiri-kanan dan align-items mengatur atas-bawah. Kalau column, keduanya bertukar.

Langkah 3: Header dengan Flexbox

Kita ingin logo di kiri dan menu di kanan, sejajar di tengah secara vertikal:

kopi-senja/style.css
/* Header: logo di kiri, menu di kanan (Flexbox) */
.site-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
padding: 1rem 1.5rem;
background: #3b2a20;
}
.logo {
color: #fff;
font-weight: 700;
font-size: 1.25rem;
text-decoration: none;
}
.nav-list {
display: flex;
gap: 1.25rem;
margin: 0;
padding: 0;
list-style: none;
}
.nav-list a {
color: #f3e3d3;
text-decoration: none;
}
  • justify-content: space-between mendorong item pertama (logo) ke ujung kiri dan item terakhir (nav) ke ujung kanan.
  • align-items: center membuat keduanya sejajar di tengah secara vertikal, walaupun ukuran hurufnya berbeda.
  • flex-wrap: wrap membolehkan menu turun ke baris baru di layar yang sangat sempit, daripada keluar dari layar.
  • .nav-list juga diberi display: flex. Flexbox bisa bersarang: satu elemen bisa menjadi flex item bagi induknya sekaligus flex container bagi anak-anaknya.

gap menggantikan kebiasaan lama memberi margin-right ke setiap item lalu menghapusnya di item terakhir.

Langkah 4: Bagian pembuka, rata tengah

Menaruh sesuatu tepat di tengah dulu terkenal sulit di CSS. Dengan Flexbox cukup beberapa baris:

kopi-senja/style.css
/* Hero: isi di tengah (Flexbox arah kolom) */
.hero {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.75rem;
min-height: 50vh;
padding: 3rem 1.5rem;
text-align: center;
}
.hero h1 {
margin: 0;
font-size: clamp(2rem, 6vw, 3.5rem);
line-height: 1.15;
}
.hero p {
margin: 0;
}
.button {
padding: 0.75rem 1.5rem;
border-radius: 999px;
background: #b45309;
color: #fff;
font-weight: 600;
text-decoration: none;
}

Karena arahnya column, justify-content: center menaruh isinya di tengah secara vertikal (setinggi 50vh, setengah tinggi layar), dan align-items: center menaruhnya di tengah secara horizontal.

clamp(2rem, 6vw, 3.5rem) membuat ukuran judul ikut membesar sesuai lebar layar (6vw, 6% dari lebar layar), tapi tidak pernah lebih kecil dari 2rem atau lebih besar dari 3.5rem. Satu baris ini menggantikan beberapa media query.

Grid: menyusun elemen dalam baris dan kolom

Grid dipakai untuk layout dua dimensi: baris dan kolom sekaligus. Kamu menentukan kolomnya di elemen pembungkus, lalu anak-anaknya otomatis mengisi sel satu per satu.

.contoh {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* tiga kolom sama lebar */
gap: 1rem;
}

Satuan fr (fraction) berarti “bagian dari sisa ruang”. 1fr 1fr 1fr membagi lebar jadi tiga bagian sama, sedangkan 2fr 1fr membuat kolom pertama dua kali lebih lebar dari kolom kedua.

Langkah 5: Kartu menu yang menyesuaikan layar

Untuk kartu menu, kita tidak ingin menentukan jumlah kolom secara pasti. Di laptop muat empat, di tablet tiga, di HP cukup satu. Grid bisa menghitungnya sendiri:

kopi-senja/style.css
/* Menu: kartu yang menyesuaikan lebar layar (Grid) */
.menu {
max-width: 1100px;
margin: 0 auto;
padding: 2rem 1.5rem 4rem;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1.25rem;
}

Baca repeat(auto-fit, minmax(220px, 1fr)) dari dalam ke luar:

  • minmax(220px, 1fr): setiap kolom minimal 220px, dan boleh melebar mengisi sisa ruang.
  • repeat(auto-fit, …): buat kolom sebanyak yang muat.

Hasilnya, browser menghitung sendiri berapa kolom 220px yang muat di layar, lalu melebarkannya supaya rata. Saat diuji di Chrome, lebar 1280 px menghasilkan empat kolom, 820 px tiga kolom, dan 390 px (ukuran HP) satu kolom. Semua tanpa media query.

max-width: 1100px dan margin: 0 auto membatasi lebar isi dan menaruhnya di tengah, supaya kartu tidak melebar sampai ujung layar monitor besar.

Langkah 6: Isi kartu, harga selalu di bawah

Kalau deskripsi kartu panjangnya berbeda-beda, harga di setiap kartu jadi tidak sejajar. Grid sudah membuat semua kartu dalam satu baris sama tinggi, jadi tinggal mendorong harga ke dasar kartu dengan Flexbox:

kopi-senja/style.css
.card {
display: flex;
flex-direction: column;
padding: 1.25rem;
border: 1px solid #e7dfd6;
border-radius: 16px;
background: #fff;
}
.card h3,
.card p {
margin: 0 0 0.5rem;
}
.card .price {
margin-top: auto;
font-weight: 700;
color: #b45309;
}

Di dalam flex container, margin-top: auto menyerap semua ruang kosong di atas elemen itu, sehingga harga terdorong ke bawah. Ini contoh yang bagus bahwa Grid dan Flexbox bukan saingan: Grid menyusun kartunya, Flexbox menyusun isi tiap kartu.

Selektornya sengaja ditulis .card .price, bukan .price saja. Alasannya dibahas di bagian error di bawah.

Langkah 7: Lokasi, beda layout untuk HP dan laptop

Bagian lokasi dan kontak cukup satu kolom di HP, tapi lebih enak dua kolom di layar lebar. Di sini kita memakai media query, aturan CSS yang hanya berlaku pada ukuran layar tertentu:

kopi-senja/style.css
/* Lokasi & kontak: satu kolom di HP, dua kolom di layar lebar */
.lokasi {
display: grid;
gap: 1.25rem;
max-width: 1100px;
margin: 0 auto;
padding: 0 1.5rem 4rem;
}
@media (min-width: 700px) {
.lokasi {
grid-template-columns: 1fr 1fr;
}
}
.site-footer {
padding: 1.5rem;
text-align: center;
background: #3b2a20;
color: #f3e3d3;
}

Gaya dasarnya ditulis untuk HP (satu kolom, bawaan grid), lalu @media (min-width: 700px) menambahkan dua kolom untuk layar yang lebarnya minimal 700 px. Cara ini disebut mobile-first: mulai dari layar kecil, lalu tambahkan aturan untuk layar yang lebih besar.

Hasil

Simpan kedua file, lalu muat ulang browser. Di laptop, kartu menu tampil empat kolom dengan harga yang sejajar di dasar kartu:

Halaman Kopi Senja di layar laptop: header cokelat dengan logo di kiri dan menu di kanan, judul besar di tengah, empat kartu menu sejajar, serta lokasi dan kontak dalam dua kolom

Di HP, kartu otomatis tersusun satu kolom dan bagian lokasi menjadi satu kolom:

Halaman Kopi Senja di layar HP selebar 390 piksel: kartu menu tersusun satu kolom dan bagian lokasi serta kontak bertumpuk

Untuk mencoba berbagai ukuran layar di laptop, buka DevTools (F12), lalu klik ikon Toggle device toolbar atau tekan Ctrl+Shift+M.

Kode CSS lengkap

kopi-senja/style.css
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: #1f2328;
background: #fbf9f6;
}
/* Header: logo di kiri, menu di kanan (Flexbox) */
.site-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
padding: 1rem 1.5rem;
background: #3b2a20;
}
.logo {
color: #fff;
font-weight: 700;
font-size: 1.25rem;
text-decoration: none;
}
.nav-list {
display: flex;
gap: 1.25rem;
margin: 0;
padding: 0;
list-style: none;
}
.nav-list a {
color: #f3e3d3;
text-decoration: none;
}
/* Hero: isi di tengah (Flexbox arah kolom) */
.hero {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.75rem;
min-height: 50vh;
padding: 3rem 1.5rem;
text-align: center;
}
.hero h1 {
margin: 0;
font-size: clamp(2rem, 6vw, 3.5rem);
line-height: 1.15;
}
.hero p {
margin: 0;
}
.button {
padding: 0.75rem 1.5rem;
border-radius: 999px;
background: #b45309;
color: #fff;
font-weight: 600;
text-decoration: none;
}
/* Menu: kartu yang menyesuaikan lebar layar (Grid) */
.menu {
max-width: 1100px;
margin: 0 auto;
padding: 2rem 1.5rem 4rem;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1.25rem;
}
.card {
display: flex;
flex-direction: column;
padding: 1.25rem;
border: 1px solid #e7dfd6;
border-radius: 16px;
background: #fff;
}
.card h3,
.card p {
margin: 0 0 0.5rem;
}
.card .price {
margin-top: auto;
font-weight: 700;
color: #b45309;
}
/* Lokasi & kontak: satu kolom di HP, dua kolom di layar lebar */
.lokasi {
display: grid;
gap: 1.25rem;
max-width: 1100px;
margin: 0 auto;
padding: 0 1.5rem 4rem;
}
@media (min-width: 700px) {
.lokasi {
grid-template-columns: 1fr 1fr;
}
}
.site-footer {
padding: 1.5rem;
text-align: center;
background: #3b2a20;
color: #f3e3d3;
}

Flexbox atau Grid?

Pakai Kalau Contoh
Flexbox elemen berjajar dalam satu arah, dan ukurannya ditentukan isinya navbar, deretan tombol, isi sebuah kartu, menaruh sesuatu di tengah
Grid elemen disusun dalam baris dan kolom sekaligus daftar kartu produk, galeri foto, kerangka halaman (sidebar + isi)

Kalau ragu, mulai dengan Flexbox. Begitu kamu mulai mengatur lebar setiap item supaya kolom-kolomnya sejajar, itu tanda kamu sebenarnya butuh Grid.

Error yang sering muncul

CSS tidak menampilkan pesan error. Kalau ada yang salah, aturannya diam-diam tidak berlaku. Ini gejala yang paling sering:

justify-content atau align-items tidak berpengaruh apa-apa. Kedua properti ini hanya bekerja di elemen yang punya display: flex atau display: grid. Pastikan kamu memasangnya di elemen pembungkus, bukan di anaknya.

Harga di kartu tidak sejajar walaupun sudah diberi margin-top: auto. Kemungkinan besar aturannya kalah oleh aturan lain. Kalau kamu menulis .price { margin-top: auto; }, aturan .card p { margin: 0 0 0.5rem; } menang, karena selektor .card p lebih spesifik (satu class dan satu tag) daripada .price (satu class saja). Saat diuji, harga kartu yang deskripsinya lebih panjang jadi turun sendiri. Solusinya, tulis .card .price. Klik kanan elemennya, pilih Inspect, dan DevTools akan menunjukkan aturan mana yang dicoret.

Halaman tampil kecil sekali di HP. Tag <meta name="viewport" content="width=device-width, initial-scale=1"> belum ada di <head>.

Ada scroll ke samping di HP. Biasanya ada elemen dengan lebar tetap yang lebih besar dari layar, misalnya width: 500px atau gambar tanpa max-width: 100%. Ganti dengan max-width, atau biarkan Grid dan Flexbox yang mengatur lebarnya.

Perubahan CSS tidak muncul. Periksa nama file di <link rel="stylesheet" href="style.css">, lalu muat ulang paksa dengan Ctrl+Shift+R supaya browser tidak memakai versi lama yang tersimpan.

Langkah berikutnya: rilis dan amankan

Halaman ini hanya berisi HTML dan CSS, jadi bisa langsung online gratis. Tarik folder kopi-senja ke Cloudflare Pages seperti di deploy pertama, dan dalam beberapa menit kamu punya link yang bisa dibagikan.

Dari sisi keamanan, halaman statis seperti ini risikonya kecil karena tidak ada data pengguna yang diproses. Yang perlu diingat: semua isi folder yang kamu unggah bisa dibaca siapa saja, jadi jangan ikutkan file pribadi. Begitu halamanmu mulai menerima input pengguna, pelajari XSS dan CSRF.

Pertanyaan yang sering diajukan

Masih perlu belajar float?

Untuk layout, tidak. float sekarang hanya dipakai untuk tujuan aslinya: membuat teks mengalir di sekeliling gambar. Kamu cukup tahu artinya kalau menemukannya di kode lama.

Bootstrap atau Tailwind saja, tidak perlu Flexbox dan Grid?

Keduanya justru memakai Flexbox dan Grid di baliknya. Class seperti flex dan justify-between di Tailwind adalah display: flex dan justify-content: space-between. Kalau konsepnya sudah paham, belajar Tailwind di level berikutnya jauh lebih cepat.

Kapan perlu media query kalau Grid bisa menyesuaikan sendiri?

Saat susunannya memang harus berubah, bukan hanya jumlah kolomnya. Misalnya menu disembunyikan di HP, atau sidebar pindah ke bawah isi. Untuk daftar kartu, repeat(auto-fit, minmax(…)) biasanya sudah cukup.

Apa bedanya auto-fit dan auto-fill?

Bedanya terlihat saat itemnya sedikit. auto-fit melebarkan item yang ada supaya memenuhi baris, sedangkan auto-fill tetap menyisakan kolom kosong. Untuk daftar yang isinya tetap, seperti empat kartu menu ini, auto-fit cocok. Untuk daftar yang jumlahnya berubah-ubah, misalnya hasil pencarian, pakai auto-fill supaya satu hasil tidak melebar selebar layar.

Kesimpulan

Flexbox menyusun elemen dalam satu arah, Grid menyusun elemen dalam baris dan kolom, dan keduanya paling kuat kalau dipakai bersama. Dengan repeat(auto-fit, minmax(…)), gap, dan margin-top: auto, kamu sudah bisa membuat sebagian besar layout yang kamu temui sehari-hari.

Halaman Kopi Senja masih statis. Di langkah berikutnya di jalur Web Developer Modern, kamu akan membuatnya hidup dengan pencarian dan keranjang belanja lewat JavaScript modern.

Bagikan:WhatsAppTelegramXFacebook
Ilustrasi jendela browser berisi tiga tahap belajar web: fondasi, komponen dan framework, lalu full-stack, diakhiri bendera online
WebRoadmap

Roadmap Web Developer 2026 untuk Pemula

Tiga level berurutan, dari halaman HTML pertama sampai aplikasi full-stack yang online. Lengkap dengan urutan belajar dan tanda kapan kamu siap naik level.

23 Oktober 20266 mnt

Ilustrasi pohon folder proyek PHP berisi composer.json, src, dan vendor, dengan baris require vendor/autoload.php yang menghubungkan ke beberapa file class
WebTutorial

PHP Modern: Versi 8, Composer, dan Autoload

Dari include satu per satu ke autoload, dari fungsi tanpa tipe ke class yang ketat. Kamu akan membuat program kasir kecil dengan fitur PHP 8 dan Composer.

9 November 202615 mnt

Ilustrasi dua kartu bersebelahan: kartu kiri berisi daftar alat lama seperti XAMPP, mysql_query, jQuery, dan FTP, kartu kanan berisi padanan modernnya seperti PHP 8, prepared statement, fetch, dan git push
WebKonsep

Apa yang Berubah di Dunia Web Sejak Era XAMPP

Kalau terakhir ngoding web dengan XAMPP, PHP native, jQuery, dan FTP, ini peta yang berubah, yang tetap sama, dan urutan mengejarnya tanpa membuang pengalamanmu.

6 November 202610 mnt

Enter bukaEsc tutupHalaman pencarian