Studi Kasus: Kartu Produk
Grid kartu responsif tanpa media query: flex-wrap + flex-basis + tombol rata bawah.
Pola kartu fleksibel
.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
<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:
.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
.isipunyaflex: 1agar mengisi tinggi kartu, dan kartu memakaiflex-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
.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
.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>yangdisplay: blockatau 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.
export default function App(): JSX.Element { return <h1>Hello world</h1> }
Tantangan
Sejajarkan Tombolnya
Di playground tombol sudah sejajar berkat margin-top: auto.
- Hapus
margin-top: autodari.tombol, amati tombol tidak sejajar. Kembalikan. - Ubah basis kartu menjadi 300px dan amati jumlah kolom berubah saat preview disempitkan.
- 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>