Kartu adalah unit terkecil dari katalog mana pun, dan kualitas katalog sangat ditentukan oleh anatomi kartunya. Bagian 2 membangun .kartu-tanaman dari tiga lapis: area media berperan sebagai “foto” produk, badan kartu berisi nama dan keterangan, lalu baris beli yang menyatukan harga dan tombol Tambah. Snapshot halaman (beranda.html) pertama kali muncul di bagian ini dan langsung memuat kedelapan kartu; skrip filter sengaja belum disertakan karena perilakunya baru dikerjakan di Bagian 5. Fokus kita sekarang: satu struktur kartu yang tampil rapi di mana pun ia diletakkan.

Anatomi Kartu Tanaman #

Setiap kartu adalah <article> dengan dua anak langsung:

html
<article class="kartu-tanaman">
  <div class="media-tanaman media--monstera" role="img" aria-label="Ilustrasi gradasi monstera">
    <span class="lencana lencana--indoor">Indoor</span>
  </div>
  <div class="badan-kartu">
    <!-- nama, keterangan, baris beli -->
  </div>
</article>

Aturan .kartu-tanaman memasang display: flex; flex-direction: column agar media selalu di atas badan, overflow: hidden agar sudut area media terpotong mengikuti radius kartu, plus border tipis, radius 12 px, dan --bayangan-1 sebagai elevasi dasar. Ketiga properti visual itu semuanya berasal dari token Bagian 1, sehingga mengubah satu token langsung mengubah seluruh deret kartu.

Area Media Berlapis Gradasi #

Area media menggantikan foto produk, dan dua properti membuatnya terasa seperti gambar sungguhan. Pertama, aspect-ratio: 4 / 3 mengunci perbandingan lebar-tinggi tanpa img apa pun, sehingga tinggi media konsisten di semua kartu meskipun lebar kolom berubah. Kedua, background-image menumpuk dua lapis linear-gradient:

css
.media--monstera {
  background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.30) 0%, rgba(255, 255, 255, 0) 55%), linear-gradient(135deg, #8fce8f 0%, #2f6b3a 100%);
}

Lapis pertama adalah kilau cahaya: putih 30% di pojok yang memudar menjadi transparan penuh pada 55% lintasan. Lapis kedua memberi warna khas tanaman — hijau muda menuju hijau daun untuk monstera. Lapisan yang ditulis lebih dulu digambar di atas, maka kilau selalu menutupi warna dasar. Delapan modifier media--* pada snapshot masing-masing memasangkan warna berbeda: hijau pekat untuk lidah mertua, merah marun untuk aglaonema, magenta untuk bougenville, dan seterusnya.

Perhatikan juga bahwa .media-tanaman adalah flex container dengan align-items: flex-start dan padding 12 px. Berkat itu, lencana cukup diletakkan sebagai anak biasa dan otomatis menumpuk rapi di pojok kiri atas — tanpa position: absolute dan tanpa pengukuran manual.

Lencana, Badan Kartu, dan Baris Beli #

.lencana membentuk pil kecil: padding 3 px 10 px, border-radius: 999px, huruf 11 px kapital dengan jarak huruf 0.06em. Empat varian mewarnainya: --indoor biru, --rimbu hijau lembut, --solar kuning hangat, dan --promo merah untuk label Terlaris atau Baru. Kartu boleh memakai dua lencana sekaligus, misalnya Indoor ditambah Terlaris.

.badan-kartu adalah flex column dengan flex: 1 supaya tingginya menyamai kartu tertinggi dalam satu baris. Kuncinya ada di .baris-beli: margin-top: auto mendorong baris harga dan tombol ke dasar kartu, sehingga harga semua kartu sejajar meski panjang keterangannya berbeda. Di dalamnya, .harga tampil tebal dengan warna utama pekat, dan .tombol (definisi dasarnya juga masuk snapshot bagian ini) memberi tombol Tambah latar hijau token dengan teks kontras.

css
/* ============================================================
   Katalog Tanaman — stylesheet utama
   Urutan: token → base → kerangka halaman → layout katalog
   → tombol → kartu tanaman → grid produk → panel filter
   → state dan gerak → responsive
   ============================================================ */

/* ---------- 1. Design token ---------- */
:root {
  /* Warna semantik tema hijau */
  --warna-latar: #f3f7f2;         --warna-permukaan: #ffffff;
  --warna-teks: #1f2a1d;          --warna-teks-lembut: #5b6b57;
  --warna-garis: #d9e4d5;         --warna-utama: #2f6b3a;
  --warna-utama-pekat: #215029;   --warna-utama-kontras: #ffffff;
  --warna-utama-lembut: #e3f0e0;  --warna-aksen: #b3372b;
  --warna-indoor: #2e5f8a;        --warna-solar: #8a5a12;
  --warna-fokus: #1d4ed8;

  /* Skala spasi 4/8 px */
  --jarak-1: 4px;  --jarak-2: 8px;
  --jarak-3: 12px; --jarak-4: 16px;
  --jarak-5: 24px; --jarak-6: 32px;
  --jarak-7: 48px; --jarak-8: 64px;

  /* Radius dan bayangan */
  --radius-kecil: 6px; --radius: 12px; --radius-penuh: 999px;
  --bayangan-1: 0 1px 2px rgba(31, 42, 29, 0.08);
  --bayangan-2: 0 6px 16px rgba(31, 42, 29, 0.14);

  /* Tipografi dan gerak */
  --font-dasar: system-ui, "Segoe UI", sans-serif;
  --tinggi-baris: 1.55;
  --durasi-cepat: 120ms; --durasi: 200ms; --pelunakan: ease-out;

  /* Kerangka halaman */
  --lebar-isi: 1120px;
  --lebar-bilah: 264px;
}

/* ---------- 2. Base ---------- */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-dasar);
  line-height: var(--tinggi-baris);
  background-color: var(--warna-latar);
  color: var(--warna-teks);
}

h1, h2, h3, p, figure { margin: 0; }
img { display: block; max-width: 100%; }

/* ---------- 3. Kerangka halaman ---------- */
.pembungkus { max-width: var(--lebar-isi); margin-inline: auto; padding-inline: var(--jarak-4); }

.laman-kepala { padding-block: var(--jarak-5); background-color: var(--warna-permukaan); border-bottom: 1px solid var(--warna-garis); }

.kepala-baris { display: flex; align-items: center; justify-content: space-between; gap: var(--jarak-3); flex-wrap: wrap; }

.brand { display: flex; align-items: center; gap: var(--jarak-3); }
.brand img { width: 40px; height: 40px; }
.brand-nama { font-size: 20px; font-weight: 700; }
.tagline { font-size: 14px; color: var(--warna-teks-lembut); }

.laman-utama { padding-block: var(--jarak-7) var(--jarak-8); }

.judul-halaman { font-size: 28px; font-weight: 800; letter-spacing: -0.01em; }
.pengantar { margin-top: var(--jarak-2); max-width: 62ch; color: var(--warna-teks-lembut); }

.laman-kaki { background-color: var(--warna-permukaan); border-top: 1px solid var(--warna-garis); }

.kaki-baris { display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--jarak-2) var(--jarak-4); padding-block: var(--jarak-5); font-size: 13.5px; color: var(--warna-teks-lembut); }

/* ---------- 4. Layout katalog: bilah filter dan isi ---------- */
.layout-katalog {
  display: grid;
  grid-template-columns: var(--lebar-bilah) minmax(0, 1fr);
  gap: var(--jarak-6);
  align-items: start;
  margin-top: var(--jarak-6);
}

.bilah-filter {
  position: sticky; top: var(--jarak-5);
  display: flex; flex-direction: column;
  gap: var(--jarak-4);
}

.isi-katalog { min-width: 0; }

/* ---------- 5. Tombol ---------- */
.tombol {
  padding: 9px 18px; border: none; border-radius: var(--radius-kecil);
  background-color: var(--warna-utama);
  color: var(--warna-utama-kontras);
  font: inherit; font-weight: 600; cursor: pointer;
}

/* ---------- 6. Kartu tanaman ---------- */
.kartu-tanaman {
  display: flex; flex-direction: column;
  overflow: hidden;
  background-color: var(--warna-permukaan);
  border: 1px solid var(--warna-garis); border-radius: var(--radius);
  box-shadow: var(--bayangan-1);
}

.media-tanaman {
  aspect-ratio: 4 / 3;
  display: flex; flex-direction: column;
  align-items: flex-start; gap: var(--jarak-2);
  padding: var(--jarak-3);
  background-color: var(--warna-utama-lembut);
}

/* Foto produk digantikan dua lapis gradasi: lapisan pertama
   kilau cahaya, lapisan kedua warna khas tiap tanaman. */
.media--monstera    { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.30) 0%, rgba(255, 255, 255, 0) 55%), linear-gradient(135deg, #8fce8f 0%, #2f6b3a 100%); }
.media--lidah       { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0) 50%), linear-gradient(135deg, #3d7a5f 0%, #163823 100%); }
.media--aglaonema   { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.30) 0%, rgba(255, 255, 255, 0) 55%), linear-gradient(135deg, #c25b5b 0%, #6b2f4a 100%); }
.media--calathea    { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0) 55%), linear-gradient(135deg, #4f8a8b 0%, #274156 100%); }
.media--pakis       { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0) 55%), linear-gradient(135deg, #679436 0%, #2c4a1e 100%); }
.media--bougenville { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.32) 0%, rgba(255, 255, 255, 0) 55%), linear-gradient(135deg, #d16ba5 0%, #7a2f5c 100%); }
.media--kamboja     { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.40) 0%, rgba(255, 255, 255, 0) 60%), linear-gradient(135deg, #f2e3b3 0%, #d9a441 100%); }
.media--melati      { background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.45) 0%, rgba(255, 255, 255, 0) 60%), linear-gradient(135deg, #eef7e9 0%, #a8c98a 100%); }

.lencana {
  padding: 3px 10px; border-radius: var(--radius-penuh);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
}

.lencana--indoor { background-color: var(--warna-indoor); color: #ffffff; }
.lencana--rimbu  { background-color: var(--warna-utama-lembut); color: var(--warna-utama-pekat); }
.lencana--solar  { background-color: #f7e3b8; color: var(--warna-solar); }
.lencana--promo  { background-color: var(--warna-aksen); color: #ffffff; }

.badan-kartu { display: flex; flex-direction: column; gap: var(--jarak-2); flex: 1; padding: var(--jarak-4); }

.nama-tanaman { font-size: 17px; font-weight: 700; line-height: 1.3; }
.keterangan { font-size: 13.5px; color: var(--warna-teks-lembut); }

.baris-beli {
  display: flex; align-items: center;
  justify-content: space-between; gap: var(--jarak-2);
  margin-top: auto; padding-top: var(--jarak-2);
}

.harga { font-size: 16px; font-weight: 700; color: var(--warna-utama-pekat); }
html
<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Katalog Tanaman</title>
  <link rel="icon" href="assets/logo.svg" type="image/svg+xml">
  <link rel="stylesheet" href="css/styles.css">
</head>
<body>
  <header class="laman-kepala">
    <div class="pembungkus kepala-baris">
      <div class="brand">
        <img src="assets/logo.svg" alt="Logo Katalog Tanaman" width="40" height="40">
        <span class="brand-nama">Katalog Tanaman</span>
      </div>
      <p class="tagline">Rumah tanam mini untuk semua rumah</p>
    </div>
  </header>

  <main class="laman-utama">
    <div class="pembungkus">
      <h1 class="judul-halaman">Katalog tanaman hias</h1>
      <p class="pengantar">Delapan tanaman pilihan untuk memulai koleksi: dari penghuni sudut ruangan sampai penyuka matahari di teras.</p>

      <section class="isi-katalog" aria-label="Daftar tanaman">
        <div class="grid-produk">
          <article class="kartu-tanaman">
            <div class="media-tanaman media--monstera" role="img" aria-label="Ilustrasi gradasi monstera">
              <span class="lencana lencana--indoor">Indoor</span>
              <span class="lencana lencana--promo">Terlaris</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Monstera Deliciosa</h2>
              <p class="keterangan">Daun lebar bercelah khas; tumbuh rapi di sudut ruangan.</p>
              <div class="baris-beli"><span class="harga">Rp95.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>

          <article class="kartu-tanaman">
            <div class="media-tanaman media--lidah" role="img" aria-label="Ilustrasi gradasi lidah mertua">
              <span class="lencana lencana--indoor">Indoor</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Lidah Mertua</h2>
              <p class="keterangan">Daun tegak berpola garis; toleran penyiraman jarang.</p>
              <div class="baris-beli"><span class="harga">Rp45.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>

          <article class="kartu-tanaman">
            <div class="media-tanaman media--aglaonema" role="img" aria-label="Ilustrasi gradasi aglaonema">
              <span class="lencana lencana--rimbu">Rimbu</span>
              <span class="lencana lencana--promo">Baru</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Aglaonema Merah</h2>
              <p class="keterangan">Daun merah marun bermotif; senang tempat teduh.</p>
              <div class="baris-beli"><span class="harga">Rp78.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>

          <article class="kartu-tanaman">
            <div class="media-tanaman media--calathea" role="img" aria-label="Ilustrasi gradasi calathea">
              <span class="lencana lencana--rimbu">Rimbu</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Calathea Orbifolia</h2>
              <p class="keterangan">Daun bulat bergaris silver; butuh kelembapan tinggi.</p>
              <div class="baris-beli"><span class="harga">Rp110.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>

          <article class="kartu-tanaman">
            <div class="media-tanaman media--pakis" role="img" aria-label="Ilustrasi gradasi pakis hias">
              <span class="lencana lencana--rimbu">Rimbu</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Pakis Hias</h2>
              <p class="keterangan">Rumpun daun rimbun untuk beranda yang teduh.</p>
              <div class="baris-beli"><span class="harga">Rp52.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>

          <article class="kartu-tanaman">
            <div class="media-tanaman media--bougenville" role="img" aria-label="Ilustrasi gradasi bougenville">
              <span class="lencana lencana--solar">Solar</span>
              <span class="lencana lencana--promo">Terlaris</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Bougenville</h2>
              <p class="keterangan">Bunga merah muda; mekar deras di matahari penuh.</p>
              <div class="baris-beli"><span class="harga">Rp60.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>

          <article class="kartu-tanaman">
            <div class="media-tanaman media--kamboja" role="img" aria-label="Ilustrasi gradasi kamboja">
              <span class="lencana lencana--solar">Solar</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Kamboja Jepang</h2>
              <p class="keterangan">Bunga kuning lembut; kuat di teras yang panas.</p>
              <div class="baris-beli"><span class="harga">Rp85.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>

          <article class="kartu-tanaman">
            <div class="media-tanaman media--melati" role="img" aria-label="Ilustrasi gradasi melati">
              <span class="lencana lencana--solar">Solar</span>
              <span class="lencana lencana--promo">Baru</span>
            </div>
            <div class="badan-kartu">
              <h2 class="nama-tanaman">Melati</h2>
              <p class="keterangan">Putih wangi sepanjang tahun; primadona pekarangan.</p>
              <div class="baris-beli"><span class="harga">Rp38.000</span><button class="tombol" type="button">Tambah</button></div>
            </div>
          </article>
        </div>
      </section>
    </div>
  </main>

  <footer class="laman-kaki">
    <div class="pembungkus kaki-baris">
      <span>Katalog Tanaman — proyek latihan CSS</span>
      <span>Semua foto tanaman digantikan gradasi warna</span>
    </div>
  </footer>
</body>
</html>

Ringkasan #

Bagian ini menghasilkan komponen inti katalog: kartu ber-anatomi media dan badan, area foto berupa dua lapis gradasi dengan aspect-ratio, lencana pil dengan empat varian warna, serta baris beli yang sejajar berkat margin-top: auto. Kedelapan kartu sudah tampil, tetapi masih bertumpuk satu kolom karena belum ada aturan grid untuk wadahnya. Bagian 3 mengatasi itu dengan satu deklarasi yang menghitung jumlah kolom sendiri.