Pesan bawaan baru muncul setelah tombol kirim ditekan — sementara pengguna ingin tahu lebih awal apakah isian sedang berada di jalur yang benar. CSS menjembatani jarak itu lewat pseudo-class status: browser melaporkan sah-tidaknya sebuah kontrol setiap saat, dan stylesheet kita tinggal menanggapi laporan itu.

Enam Status Form #

Pseudo-classAktif saat
:validnilai memenuhi seluruh kendala kontrol
:invalidada kendala yang dilanggar
:requiredkontrol memiliki atribut required
:optionalkontrol tanpa required
:in-rangenilai berada dalam rentang min–max
:out-of-rangenilai berada di luar rentang

Status diperbarui langsung saat pengguna mengetik — tanpa JavaScript, tanpa event handler. Pemakaian paling umum: border hijau untuk sah, border merah untuk tidak sah.

Contoh: Umpan Balik Warna #

html
<style>
  input:valid:not(:placeholder-shown) {
    border: 2px solid #27ae60;
  }
  input:invalid:not(:placeholder-shown) {
    border: 2px solid #c0392b;
  }
</style>
<form action="/daftar" method="post">
  <label for="surel">Alamat email</label>
  <input type="email" id="surel" name="surel" placeholder="[email protected]" required>
  <label for="kode">Kode pos</label>
  <input type="text" id="kode" name="kode" pattern="[0-9]{5}" placeholder="10110" required>
  <button type="submit">Daftar</button>
</form>

Hasil Render:

  • Kolom email bergaris hijau saat nilainya berbentuk [email protected]; bergaris merah saat nilainya masih budi@.
  • Kolom kode pos hijau setelah tepat lima digit; bergaris merah lagi ketika digit keenam diketik.

Mari kita telaah kode di atas:

  1. Baris 2–4 (:valid:not(:placeholder-shown)): warna hijau hanya saat kotak sudah berisi ketikan — :placeholder-shown masih aktif selama placeholder tampil, artinya isi kotak dianggap belum tersentuh.
  2. Baris 5–7 (:invalid:not(:placeholder-shown)): warna merah juga menunggu isi; keduanya dijaga agar status tidak bereaksi terlalu dini.
  3. Baris 11 dan 13 (placeholder): trik ini menuntut placeholder pada tiap kontrol yang ditanggapi — kotak tanpa placeholder tidak pernah menampilkan placeholder, sehingga :not(:placeholder-shown) selalu benar dan merahnya menyala sejak awal.

Jebakan: Merah Sebelum Disentuh #

Perilaku bawaan :invalid memancing keluhan klasik: kolom required yang kosong sudah tidak sah sejak halaman dimuat. Selector polos input:invalid mengecat merah seluruh kolom wajib sebelum pengguna sempat mengetik satu huruf — pemandangan yang membuat form terasa menghakimi di detik pertama. Solusi pada contoh di atas menunda pewarnaan sampai ada isi: kombinasi :not(:placeholder-shown), atau pseudo-class :user-invalid pada browser modern — status yang baru aktif setelah pengguna berinteraksi dengan kontrolnya.

Ringkasan #

  • :valid/:invalid, :required/:optional, :in-range/:out-of-range melaporkan status kendala ke CSS.
  • Status diperbarui langsung saat mengetik — tanpa JavaScript.
  • :invalid aktif sejak awal; padukan :not(:placeholder-shown) agar merah hanya muncul setelah kolom berisi.
  • Warna selalu ditemani ikon atau teks demi aksesibilitas.

Chapter berikutnya mengupas teks yang muncul saat penolakan terjadi: pesan validasi bawaan dan batas kustomisasinya.