Form modern tidak butuh JavaScript untuk mengetahui bahwa sebuah isian salah. Cukup dengan attribute HTML seperti required dan type="email", browser sudah menjalankan constraint validation dan menandai setiap kolom sebagai valid atau tidak valid — dan CSS bisa bereaksi terhadap keadaan itu lewat pseudo-class khusus. Masalahnya, versi paling kasarnya menyalakan tanda merah sebelum pengguna sempat mengetik apa pun. Pada chapter ini kita lihat pseudo-class yang tersedia, mengapa :invalid saja tidak cukup, dan bagaimana :user-valid serta :user-invalid memperbaiki pengalamannya.
Pseudo-class Validasi dari HTML #
Empat pseudo-class dasar membaca keadaan validasi yang dihitung browser:
| Pseudo-class | Cocok ketika |
|---|---|
:required | kolom memiliki attribute required |
:optional | kolom tidak memiliki attribute required |
:valid | nilai kolom memenuhi seluruh batasan yang berlaku |
:invalid | nilai kolom melanggar minimal satu batasan |
Batasan itu datang dari HTML, bukan CSS: required menuntut kolom terisi, type="email" menuntut pola alamat email, dan attribute minlength menuntut panjang minimal. CSS hanya membaca hasil perhitungannya:
.kolom-email:invalid {
border-color: #b3362b;
}
.kolom-email:valid {
border-color: #1f6f54;
}
.kolom-email:required {
border-left: 4px solid #f4b942;
}Demo berikut belum disentuh apa pun, tetapi kolomnya sudah merah — isi alamat sah untuk melihatnya berubah hijau:
Masalah: Merah yang Muncul Terlalu Dini #
Perhatikan kejanggalan pada contoh di atas. Halaman baru saja dibuka, pengguna belum menyentuh apa pun, tetapi kolom email sudah merah — karena kolom kosong yang required memang cocok dengan :invalid sejak awal. Form yang menghukum pengguna sebelum mereka melakukan kesalahan memberi kesan buruk dan membuat tanda merah kehilangan maknanya.
Solusinya adalah pasangan pseudo-class yang lebih cerdas: :user-valid dan :user-invalid. Keduanya hanya cocok setelah pengguna benar-benar berinteraksi dengan kolom — mengetik lalu berpindah kolom, misalnya. Sebelum sentuhan pertama, kedua pseudo-class itu tidak mencocokkan apa pun:
.kolom-email:user-invalid {
border-color: #b3362b;
}
.kolom-email:user-valid {
border-color: #1f6f54;
}Perbandingan perilakunya:
| Pseudo-class | Muncul kapan | Cocok untuk |
|---|---|---|
:invalid | Langsung, sejak halaman dimuat | Deteksi teknis, menandai kolom wajib sebelum submit |
:user-invalid | Setelah pengguna mengubah isi kolom | Umpan balik kesalahan yang adil |
Perlu diketahui, styling ini berjalan di atas mekanisme submit bawaan browser: form yang masih memiliki kolom :invalid tidak akan terkirim, dan browser menampilkan gelembung pesan miliknya sendiri. CSS kita tidak mengubah perilaku itu — ia menambahkan umpan balik visual yang lebih awal dan lebih lembut sebelum pengguna sampai ke tombol submit. Bila validasi kustom penuh dibutuhkan, attribute novalidate pada <form> mematikan mekanisme bawaan tersebut dan pengurusannya pindah ke JavaScript, yang berada di luar cakupan course CSS ini.
Pesan Error dan Sukses dengan Sibling Selector #
Border berwarna bagus, tetapi pengguna butuh kalimat yang menjelaskan. Pola yang umum: letakkan elemen pesan tepat setelah input, sembunyikan secara bawaan, lalu tampilkan lewat general sibling selector ~ dari section Selectors:
<label for="demo-email">Email</label>
<input id="demo-email" class="kolom-email" type="email" required>
<p class="pesan-email">Tulis alamat email yang sah, misalnya [email protected]</p>.pesan-email {
display: none;
margin: 6px 0 0;
font-size: 0.875rem;
color: #b3362b;
}
.kolom-email:user-invalid ~ .pesan-email {
display: block;
}
.kolom-email:user-invalid {
border-color: #b3362b;
}Karena pesannya paragraf sungguhan, ia bisa dibacakan pembaca layar dan tidak bergantung pada warna border semata. Seluruh perpindahan state pada demo ini dihitung browser dari attribute type="email" dan required — tanpa JavaScript.
Ringkasan #
HTML constraint validation menyediakan state-nya, CSS menyediakan tampilannya: :required dan :optional menandai kebijakan kolom, sedangkan :valid dan :invalid membaca hasil perhitungan browser. Untuk umpan balik yang adil, :user-valid dan :user-invalid menunda reaksi sampai pengguna benar-benar menyunting kolom, dan pesan kesalahan tampil lewat sibling selector alih-alih bergantung pada warna border. Chapter berikutnya membahas dua state yang arahnya berbeda — bukan tentang isi yang salah, melainkan tentang kolom yang sengaja dikunci: disabled dan readonly.