Menyalin-tempel satu blok aturan tombol ke tiga tombol berbeda memang selesai cepat, tetapi perubahan radius berikutnya harus dilakukan di tiga tempat — dan satu tempat selalu terlewat. Pengulangan adalah sumber utama tampilan yang tidak konsisten dan berkas CSS yang membengkak. Chapter ini menyusun strategi merapikan pengulangan: base class plus modifier, custom property untuk nilai berulang, selector list dan :is(), lalu menutup dengan batas kapan pengulangan boleh dibiarkan.

Tiga Salinan Tombol #

Kasus yang paling sering dijumpai adalah tiga tombol dengan warna berbeda. Versi salin-tempelnya tampak seperti ini:

css
.tombol-simpan {
  background-color: #14503a;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  padding: 10px 16px;
  font-size: 15px;
}

.tombol-batal {
  background-color: #e2e8f0;
  color: #1f2933;
  border: none;
  border-radius: 8px;
  padding: 10px 16px;
  font-size: 15px;
}

.tombol-bahaya {
  background-color: #b3261e;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  padding: 10px 16px;
  font-size: 15px;
}

Delapan belas deklarasi mengisi aturan ini dan dua belas di antaranya identik. Menambah tombol keempat berarti menyalin enam baris lagi, lalu mengingat di berapa tempat padding perlu diubah.

Base Class plus Modifier #

Pola perbaikannya sudah kita latih di chapter penamaan: satu base class menampung kesamaan, modifier menampung perbedaan:

css
.tombol {
  border: none;
  border-radius: 8px;
  padding: 10px 16px;
  font-size: 15px;
}

.tombol--simpan {
  background-color: #14503a;
  color: #ffffff;
}

.tombol--batal {
  background-color: #e2e8f0;
  color: #1f2933;
}

.tombol--bahaya {
  background-color: #b3261e;
  color: #ffffff;
}

Markup memakai dua class: class="tombol tombol--simpan". Jumlah baris tidak selalu jauh lebih pendek, tetapi jumlah tempat yang harus diubah pasti berkurang — inilah ukuran sebenarnya. Tombol baru hanya butuh satu blok dua deklarasi, dan perubahan padding cukup dilakukan satu kali.

Kesamaan kini hidup di satu tempat bernama .tombol.

Demo berikut menampilkan versi salin-tempel dan versi base plus modifier secara berdampingan:

Mengubah padding pada base class memindahkan tiga tombol sekaligus — pada versi salin-tempel, tiga aturan harus disunting satu per satu.

Custom Property untuk Nilai yang Berulang #

Base class menyatukan aturan di dalam satu komponen; custom property menyatukan nilai lintas komponen. Ketika radius yang sama dipakai tombol, badge, dan panel, angka itu layak menjadi token:

css
:root {
  --radius-sedang: 8px;
}

.tombol {
  border-radius: var(--radius-sedang);
}

.badge-status {
  border-radius: var(--radius-sedang);
}

.panel-notifikasi {
  border-radius: var(--radius-sedang);
}

Mengubah nilai token cukup sekali dan tiga komponen ikut bergerak. Manfaat tambahannya: keputusan desain terdokumentasi sebagai nama — “radius sedang” jelas konsepnya, sementara angka 8px yang tersebar tidak.

Selector List dan :is() #

Untuk aturan yang benar-benar identik lintas selector, selector list menghindari duplikasi blok, dan :is() memberi bentuk yang lebih ringkas:

css
.tombol, .badge-status, .panel-notifikasi {
  font-family: system-ui, sans-serif;
}

:is(h1, h2, h3) {
  line-height: 1.25;
}

Satu pengingat dari chapter specificity: :is() mengambil bobot tertinggi dari argumennya, sehingga :is(#utama, .kartu) p berbobot (1, 0, 1). Kelompokkan selector yang bobotnya setara agar kejutan specificity tidak muncul.

Batas DRY: Keterbacaan Tetap Utama #

Prinsip DRY (Don’t Repeat Yourself) bukan target nol pengulangan. Menyatukan dua aturan yang kebetulan mirip sering menghasilkan selector panjang atau class abstrak yang sulit dijelaskan — biayanya keterbacaan. Beberapa patokan yang sehat:

  • abstraksikan ketika konsepnya sama, bukan hanya nilainya kebetulan sama;
  • tunggu pola berulang tiga kali atau lebih sebelum menyatukan;
  • utamakan pembaca berikutnya: pengulangan enam baris yang jelas lebih baik daripada satu aturan cerdik yang harus diuraikan panjang.

Kesalahan Umum #

Strategi DRY juga bisa salah pakai, dan bentuk salah pakainya konsisten. Tiga kesalahan berikut paling sering muncul saat merapikan kode yang berulang:

KesalahanAkibatPerbaikan
Menyatukan dua aturan yang kebetulan nilainya samamengubah satu komponen ikut mengubah komponen lainulangi terpisah, atau samakan konsepnya terlebih dulu
Menaruh property yang bervariasi di base classsetiap modifier menimpanya, arti base kaburbase hanya berisi property yang benar-benar sama
Selector list melebar tanpa batassulit dilacak saat debuggingpecah per kelompok yang bermakna

Semuanya bermuara pada satu hal: abstraksi yang dibuat terlalu dini justru lebih mahal daripada pengulangan yang tertata rapi.

Ringkasan #

Pengulangan ditangani tiga alat: base class plus modifier untuk kesamaan aturan, custom property untuk nilai yang sama lintas komponen, dan selector list atau :is() untuk aturan identik. Semua alat itu tunduk pada satu prinsip: keterbacaan menang atas kecerdikan. Kode yang sudah ringkas kini butuh fondasi yang rata di seluruh browser — topik chapter berikutnya tentang reset dan normalize.