Checkbox dan radio adalah kontrol yang paling keras kepala untuk ditata: bentuk kotak dan titiknya digambar browser, dan banyak property biasa seperti border-radius tidak berpengaruh pada tampilan bawaannya. Kabar baiknya ada dua jalan yang bisa dipilih sesuai kebutuhan. Jalan pertama hanya satu baris dan mempertahankan rasa native; jalan kedua membangun kontrol sepenuhnya dari nol dan membuka kemungkinan seperti toggle switch. Pada chapter ini kita bahas keduanya, plus satu aturan aksesibilitas yang tidak boleh dilanggar saat membangun versi kustom.

Dua Pendekatan, Dua Tujuan #

PendekatanCara kerjaCocok untuk
accent-colorMengganti warna aksen kontrol bawaan, bentuknya tetap milik browserMayoritas form; cepat, aman, terasa native
appearance: none + :checkedKulit bawaan dilepas; kotak, titik, dan state digambar CSS sendiriDesain kustom seperti toggle switch dan kartu pilihan

Aturan memilihnya sederhana: mulai dari accent-color, dan naik ke pendekatan kustom hanya bila desain benar-benar menuntut bentuk yang berbeda.

Pendekatan Cepat: accent-color #

Property accent-color — sudah dibahas sekilas pada section Pseudo-classes — mewarnai bagian aktif checkbox, radio, dan beberapa kontrol lain tanpa menyentuh bentuknya:

css
.grup-preferensi input {
  accent-color: #1f6f54;
}

Centang dan pilih kontrol pada demo berikut: warna aksennya mengikuti accent-color, sedangkan bentuk dan interaksinya tetap milik browser:

Karena tampilannya konsisten dengan kontrol lain di perangkat pengguna, pendekatan ini nyaman dipakai untuk form kerja sehari-hari.

Pendekatan Kustom: appearance none plus :checked #

Untuk menggambar checkbox versi sendiri, kita melepas kulit bawaannya dengan appearance: none, lalu menata state tercentang lewat pseudo-class :checked:

css
.kotak-kustom input {
  appearance: none;
  width: 20px;
  height: 20px;
  border: 2px solid #c7d2cb;
  border-radius: 6px;
  background-color: #fdfaf3;
  cursor: pointer;
}

.kotak-kustom input:checked {
  border-color: #1f6f54;
  background-color: #1f6f54;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='10'%3E%3Cpath d='M1 5l3.5 3.5L11 1' fill='none' stroke='%23fdfaf3' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
}

.kotak-kustom input:checked + .teks-opsi {
  color: #14503a;
  font-weight: 600;
}

Centang opsinya pada demo berikut: kotak 20px terisi hijau dengan tanda centang putih, dan teks opsinya ikut menggelap lewat sibling selector:

Penting dipahami: appearance: none hanya melepas tampilan bawaan. Input tetap dirender, tetap bisa difokus dengan Tab, tetap bisa diklik, dan tetap terbaca pembaca layar — kita hanya mengganti gambar kotaknya. Perhatikan pula pola label yang membungkus input:

html
<label class="kotak-kustom">
  <input type="checkbox" name="topping">
  <span class="teks-opsi">Keju tambahan</span>
</label>

Klik di mana pun di dalam label akan men-toggle input, dan hubungan ini berlaku tanpa atribut for karena input berada di dalam label itu sendiri.

Membangun Toggle Switch #

Toggle switch — sakelar on/off ala pengaturan ponsel — adalah checkbox yang menyamar. Kotaknya kita lebarkan menjadi lintasan, dan bulatan penunjuknya kita gambar memakai background radial-gradient yang berpindah posisi ketika :checked:

css
.saklar input {
  appearance: none;
  width: 44px;
  height: 24px;
  border-radius: 999px;
  background-color: #b9c4bf;
  background-image: radial-gradient(circle at 12px 12px, #fdfaf3 0 9px, transparent 10px);
  cursor: pointer;
}

.saklar input:checked {
  background-color: #1f6f54;
  background-image: radial-gradient(circle at 32px 12px, #fdfaf3 0 9px, transparent 10px);
}

.saklar input:focus-visible {
  outline: 2px solid #1f6f54;
  outline-offset: 2px;
}

Klik sakelar berikut: lintasannya berubah hijau dan bulatan putihnya berpindah ke kanan:

Perpindahan state pada demo-demo di atas digerakkan CSS semata melalui :checked — tanpa JavaScript.

Mari kita bedah tekniknya:

  1. border-radius: 999px: membuat kotak 44x24px menjadi kapsul penuh, bentuk standar track sakelar.
  2. radial-gradient(circle at 12px 12px, ...): menggambar satu bulatan pejal di titik 12px, 12px; perhentian warna #fdfaf3 0 9px, transparent 10px menghasilkan tepi bulatan yang rapi tanpa gradasi.
  3. circle at 32px 12px pada :checked: bulatan yang sama digambar ulang lebih ke kanan, sehingga state on dan off hanya berbeda posisinya.
  4. :focus-visible: karena kita sudah menggambar sendiri, indikator fokus juga tanggung jawab kita; jangan sampai sakelar ini tidak terlihat posisinya saat dinavigasi keyboard.

Perpindahan bulatan saat ini terjadi dalam satu lompatan. Bila ingin gerakannya halus, property transition yang dibahas pada section Transitions dan Animations bisa menganimasikan background-image bersama background-color.

Ringkasan #

Checkbox dan radio punya dua jalan styling: accent-color untuk mewarnai kontrol native dalam satu baris, dan appearance: none plus :checked untuk menggambarnya dari nol — termasuk toggle switch yang dibangun dari lintasan kapsul dan bulatan radial-gradient. Apa pun jalannya, input tidak boleh dibuang dari markup; ia tetap menjadi sumber state dan titik fokus keyboard. Chapter berikutnya turun ke kontrol yang paling sering diklik: tombol, beserta sistem varian dan ukurannya.