Halaman modern bukan lagi satu lembar markup panjang, melainkan gabungan potongan yang dipakai ulang: kartu, tombol, badge, dan form yang muncul di banyak tempat. Component-based CSS menyelaraskan cara kita menulis stylesheet dengan cara kita membangun markup: setiap komponen memiliki gaya yang kohesif, mandiri dari halaman tempat komponen itu dipasang, dan menyediakan variasi tanpa menyalin kode. Dengan pendekatan ini, memindahkan satu komponen ke halaman lain tidak menuntut perbaikan selector. Chapter ini membahas anatomi komponen, variasi lewat modifier class, dan komposisi antar-komponen.

Komponen sebagai Unit Mandiri #

Sebuah komponen adalah pasangan markup dan CSS yang berakar pada satu class — .kartu, .tombol, .badge. Seluruh selector komponen ditulis dengan akar tersebut, bukan dengan rantai turunan dari halaman:

.kartu {
  background-color: rgb(255, 255, 255);
  border: 1px solid rgb(226, 232, 240);
  border-radius: 12px;
  padding: 16px;
}
.kartu__judul {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 700;
  color: rgb(15, 23, 42);
}
.kartu__isi {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.5;
  color: rgb(71, 85, 105);
}
.kartu__aksi {
  display: flex;
  column-gap: 8px;
}

Tiga keputusan di atas menuntut komponen tersebut mandiri:

  1. Satu class sebagai akar: .kartu menetapkan wadah; gaya tidak bergantung pada class halaman seperti .beranda .kartu, sehingga kartu tampil sama di mana pun dipasang.
  2. Bagian internal diberi nama sendiri (.kartu__judul, konvensi BEM yang dibedah tuntas pada Chapter BEM ): selector pendek satu class, tanpa nesting seperti .kartu h3 yang membocorkan gaya ke <h3> milik komponen lain di dalam kartu.
  3. Tidak ada asumsi kontekstual: komponen tidak menebak induknya; urutan file yang mengatur mana yang menang telah kita atur pada Chapter Mengorganisasi File CSS .

Variasi lewat Modifier #

Komponen yang sehat menyediakan variasi melalui modifier class tambahan, bukan melalui penyalinan seluruh komponen:

css
.kartu--sorot {
  border-color: rgb(2, 132, 199);
  background-color: rgb(239, 246, 255);
}

Markup memakai keduanya sekaligus: class="kartu kartu--sorot". Gaya dasar tetap berlaku; modifier hanya menimpa bagian yang berbeda. Pola ini menjaga CSS tetap kecil karena variasi hanya berisi selisihnya, dan markup tetap jelas karena pembaca langsung melihat nama variannya. Kontras dengan pendekatan “satu class per keadaan” seperti .kartu-biru-border-tebal — kombinasi gaya baru berarti class baru, dan jumlahnya berkembang tak terkendali.

Batasnya perlu disepakati sejak awal: modifier hanya berisi properti yang benar-benar berbeda dari komponen dasarnya, dan modifier tidak boleh saling bercampur begitu banyak sehingga setiap kombinasi harus diuji satu per satu. Dua sampai tiga variasi per komponen adalah titik yang sehat; bila kebutuhan variasi bertambah banyak, itu sinyal komponen perlu dipecah menjadi komponen yang lebih kecil.

Komposisi Antar-Komponen #

Komponen kecil yang mandiri dapat disusun menjadi komponen yang lebih besar tanpa mengubah satu pun selector: badge diletakkan di dalam kartu, kartu di dalam grid. Badge pada demo berikut adalah komponen terpisah yang dipasang di area aksi kartu:

html index.html
<div class="kartu kartu--sorot">
  <h3 class="kartu__judul">Laporan Bulanan</h3>
  <p class="kartu__isi">Ringkasan penjualan bulan ini sudah tersedia.</p>
  <div class="kartu__aksi">
    <span class="badge">Baru</span>
    <button class="tombol">Buka</button>
  </div>
</div>

Hasil di Browser:

text
Kartu dasar tampil putih dengan sudut 12px; kartu varian --sorot
tampil dengan border biru rgb(2, 132, 199) dan latar rgb(239, 246, 255).
Judul kartu berukuran 18px; area aksi menjadi flex dengan jarak kolom 8px.
Badge tampil membulat penuh (border-radius 999px) dengan latar biru.

Mari kita telaah keputusan kuncinya:

  1. class="kartu kartu--sorot": elemen memakai komponen dasar sekaligus variannya; selisih gaya hanya border dan latar.
  2. .kartu__aksi dengan display: flex: area aksi adalah bagian komponen, sehingga penyusunan tombol dan badge diatur oleh kartu, bukan oleh halaman.
  3. .badge tetap berdiri sendiri: badge tidak tahu ia berada di dalam kartu; gaya pemisahan jarak datang dari column-gap milik induknya.

Component-based CSS adalah pola paling fundamental di section ini: BEM memberikan disiplin penamaannya, utility classes mempercepat penyusunannya, dan design tokens mengatur nilainya.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

contoh-kartu.css

Unduh berkas
css
.kartu {
  background-color: rgb(255, 255, 255);
  border: 1px solid rgb(226, 232, 240);
  border-radius: 12px;
  padding: 16px;
}
.kartu__judul {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 700;
  color: rgb(15, 23, 42);
}
.kartu__isi {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.5;
  color: rgb(71, 85, 105);
}
.kartu__aksi {
  display: flex;
  column-gap: 8px;
  align-items: center;
}
.kartu--sorot {
  border-color: rgb(2, 132, 199);
  background-color: rgb(239, 246, 255);
}