cssflexboxkartustudi-kasusMenengah5 mnt baca

Studi Kasus: Kartu Produk

Grid kartu responsif tanpa media query: flex-wrap + flex-basis + tombol rata bawah.

Pola kartu fleksibel

css
.grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.kartu {
  flex: 1 1 240px; /* grow, boleh susut, basis 240px */
  display: flex;
  flex-direction: column;
}

flex: 1 1 240px adalah resep grid responsif tanpa media query: tiap kartu minimal 240px, mekar mengisi baris, dan turun baris saat sempit.

Struktur kartu vertikal

html
<article class="kartu">
  <img src="..." alt="...">
  <div class="isi">
    <h3>Nama Produk</h3>
    <p>Deskripsi singkat.</p>
    <a class="tombol" href="#">Beli</a>
  </div>
</article>

Trik tombol rata bawah

Masalah klasik: deskripsi beda panjang bikin tombol tidak sejajar antar kartu. Solusinya margin auto vertikal:

css
.kartu .isi {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 16px;
}

.kartu .tombol {
  margin-top: auto; /* dorong ke bawah! */
}

margin-top: auto menyerap semua ruang sisa di atas tombol, mendorongnya ke dasar kartu. Semua tombol sejajar apa pun panjang deskripsinya.

Catatan teknis: pastikan .isi punya flex: 1 agar mengisi tinggi kartu, dan kartu memakai flex-direction: column. Tanpa itu, margin auto tidak punya ruang untuk diserap.

Kenapa kartu butuh flex-direction: column?

Kartu adalah tumpukan vertikal: gambar, judul, deskripsi, tombol. Tanpa column flex, tombol "margin-top: auto" tidak punya ruang untuk diserap. Struktur column + flex: 1 pada isi adalah fondasi pola ini.

Contoh: kartu dengan harga dan tombol sejajar

css
.kartu .isi {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 16px;
}

.harga {
  font-size: 1.25rem;
  font-weight: 800;
  margin-bottom: 12px;
}

.kartu .tombol {
  margin-top: auto;
}

Harga tepat di atas tombol, tombol selalu di dasar. Rapi walau deskripsi beda panjang.

Contoh: badge "stok habis" overlay

css
.kartu {
  position: relative;
}

.stok-habis::after {
  content: "Stok Habis";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.7);
  font-weight: 700;
  color: #64748b;
}

Jebakan

Lupa flex: 1 pada .isi. Tanpa itu, .isi hanya setinggi kontennya dan margin-top: auto tidak punya ruang. Kartu juga butuh display: flex; flex-direction: column.

Gambar beda tinggi merusak keseragaman. Samakan tinggi gambar kartu dengan height + object-fit: cover (lihat modul object-fit).

Tips profesional

  • Samakan tinggi gambar kartu: height: 180px; object-fit: cover; agar grid kartu terlihat profesional.
  • Tambahkan transition: transform 0.3s, box-shadow 0.3s; + hover lift untuk kartu yang terasa interaktif.
  • Untuk kartu klik-penuh (seluruh kartu adalah link), bungkus dengan <a> yang display: block atau pakai trik stretched-link.

Rangkuman

Kartu responsif = flex-wrap + flex: 1 1 basis. Tombol rata bawah = margin-top: auto di dalam kolom flex. Dua pola ini menyelesaikan 90% kebutuhan grid kartu.

Live Playground
export default function App(): JSX.Element {
  return <h1>Hello world</h1>
}

Edit kode di kiri, preview kanan ter-update otomatis.

Tantangan

Sejajarkan Tombolnya

Di playground tombol sudah sejajar berkat margin-top: auto.

  1. Hapus margin-top: auto dari .tombol, amati tombol tidak sejajar. Kembalikan.
  2. Ubah basis kartu menjadi 300px dan amati jumlah kolom berubah saat preview disempitkan.
  3. Tambahkan badge "Laris" di pojok kartu pertama memakai absolute + relative (gabungkan dengan modul positioning).
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<h1>Halo CSS</h1>
<p>Edit styles.css dan lihat hasilnya.</p>
</body>
</html>