Chapter-chapter sebelumnya membahas state satu per satu: :hover untuk kursor, :focus-visible untuk keyboard, :active untuk tekan, dan :disabled untuk kontrol nonaktif. Di proyek nyata, kelima state itu hidup berdampingan pada satu komponen, dan kualitasnya terasa dari konsistensinya: tombol yang terangkat saat hover harus juga tenggelam saat ditekan, dan indikator fokusnya harus tetap terlihat di tengah semua perubahan. Pada chapter penutup section ini, kita menyusun matriks state untuk satu tombol dan menjadikannya template yang bisa dipakai ulang.

Matriks State untuk Satu Komponen #

Cara kerja yang disarankan: sebelum menulis CSS, tentukan keputusan visual untuk setiap state dalam bentuk tabel. Dengan begitu pilihan gaya menjadi keputusan desain yang disengaja, bukan kebetulan bertumpuk:

StateSelectorKeputusan visual
Default.tombol-aksiwarna dasar, bayangan tipis sebagai pijakan
Hover:hoverwarna menggelap, bayangan melebar, tombol naik 1px
Active:activewarna paling gelap, tombol turun 2px, bayangan menyusut
Focus keyboard:focus-visibleoutline kontras di luar tombol, offset 2px
Disabled:disabledpudar, tanpa bayangan, kursor not-allowed

Tabel semacam ini juga menjadi alat komunikasi dengan desainer dan penguji: setiap baris punya jawaban, dan tidak ada state yang terlupa.

Menyusun Tombol yang Konsisten #

css
.tombol-aksi {
  padding: 12px 24px;
  border: none;
  border-radius: 10px;
  background-color: #1f6f54;
  color: #fdfaf3;
  font-size: 15px;
  cursor: pointer;
  box-shadow: 0 2px 4px rgb(13 59 42 / 0.35);
}

.tombol-aksi:hover {
  background-color: #14503a;
  box-shadow: 0 6px 14px rgb(13 59 42 / 0.28);
  transform: translateY(-1px);
}

.tombol-aksi:active {
  background-color: #0d3b2a;
  box-shadow: 0 1px 2px rgb(13 59 42 / 0.35);
  transform: translateY(2px);
}

.tombol-aksi:focus-visible {
  outline: 3px solid #f4b942;
  outline-offset: 2px;
}

.tombol-aksi:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

Seluruh matriks di atas hidup pada dua tombol berikut — satu aktif, satu disabled. Coba arahkan kursor, tekan dan tahan, lalu tekan Tab hingga fokus tiba:

Mari kita telaah keputusan-keputusan di baliknya:

  1. Tiga properti bekerja sebagai satu sistem: background-color menandai arah perubahan, box-shadow mengatur kedalaman, dan transform menggerakkan tombol. Ketiganya bergerak serempak, bukan masing-masing sendiri.
  2. Arah perubahan konsisten: hover mengangkat (bayangan melebar, posisi naik), sedangkan active menekan (bayangan menyusut, posisi turun). Pengguna menangkap logika “naik = tersedia, turun = sedang ditekan” tanpa perlu diajarkan.
  3. Fokus berada di luar kotak: outline dengan outline-offset tidak menggeser tata letak, sehingga cincin fokus tidak memindahkan tombol maupun tetangganya.
  4. Disabled menetralkan transformasi: transform: none memastikan tombol nonaktif tidak ikut terangkat saat kursor lewat, karena pada beberapa browser :hover tetap cocok pada elemen disabled.

Perlu diingat, CSS hanya menata state disabled; pemasangan dan pelepasan attribute-nya terjadi di HTML atau JavaScript. Tugas stylesheet kita adalah memastikan setiap keadaan itu terlihat benar.

Ingat pula bahwa state bisa bertumpuk pada satu momen: tombol yang ditekan dengan kursor di atasnya cocok dengan :hover dan :active sekaligus, dan tombol yang terfokus lewat Tab lalu diarahkan kursor cocok dengan :focus-visible dan :hover. Matriks di atas sudah siap untuk semua kombinasi karena urutan penulisan menentukan siapa menimpa siapa — gaya :active ditulis setelah :hover, dan outline fokus berdiri sendiri sehingga tidak bersaing dengan warna latar.

Template yang sama berlaku lintas komponen: tautan bergaya tombol mewarisi matriks serupa dari chapter Styling Links, sedangkan kartu yang bisa diklik cukup menyalin pasangan hover dan active-nya. Sekali matriksnya matang, konsistensi antarkomponen menjadi hasil sampingan yang menyenangkan.

Menghormati Preferensi Gerakan #

Efek naik-turun adalah gerakan; sebagian pengguna menyetel sistemnya untuk mengurangi animasi. Media query prefers-reduced-motion membaca preferensi itu — di section Transitions dan Animations kita membahasnya tuntas, dan untuk sekarang cukup satu pola penutup gerakan:

css
@media (prefers-reduced-motion: reduce) {
  .tombol-aksi:hover,
  .tombol-aksi:active {
    transform: none;
  }
}

Media query ini hanya menetralkan perpindahan posisi; umpan balik lewat warna dan bayangan tetap berlaku bagi pengguna yang memilih gerakan dikurangi.

Ringkasan #

Matriks state mengubah lima pseudo-class dari pengetahuan terpisah menjadi satu komponen yang utuh: warna, bayangan, dan transform bergerak sebagai satu sistem dengan arah yang konsisten, sementara outline fokus tetap berada di luar tata letak dan disabled menetralkan semuanya. Dengan template ini, setiap tombol di proyek berikutnya tinggal menyalin keputusan yang sudah matang. Section ini sekaligus beralih peran: pada section Styling Forms dan Controls, seluruh state yang kita kuasai akan diterapkan pada kontrol form yang sesungguhnya — input, select, checkbox, dan tombol kirim.