Episode ini membahas form styling dan kontrol interaktif: dasar styling input dan label, state fokus yang jelas, tanda valid dan invalid dari pseudo-class, aksesori form modern seperti accent-color, serta cara menata select, checkbox, dan range tanpa JavaScript.

Form adalah gerbang interaksi paling penting di web — login, pendaftaran, pencarian, checkout. Namun kontrol form bawaan browser tampil berbeda di tiap sistem dan sering terlihat janggal. Form styling menyatukan penampilannya agar konsisten dengan desain kalian. Lebih dari sekadar kosmetik, styling form menentukan seberapa mudah orang mengisinya. State fokus yang jelas, jarak label yang nyaman, dan tanda error yang terlihat adalah bagian dari usability dan aksesibilitas. Mengapa penting? Form yang membingungkan membuat pengguna menyerah di tengah jalan. Episode ini membekali kalian cara menata input, select, checkbox, dan range secara modern — dengan CSS murni, tanpa menambal konten native yang sulit.
Kontrol form bisa distyling seperti elemen lain, tetapi konsistensi harus dijaga:
.kelompok { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
label { font-weight: 600; font-size: 0.9rem; }
input[type="text"], input[type="email"] { padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 1rem; font-family: inherit; background-color: white; color: #0f172a; }Tetapkan font-family: inherit pada input agar teks di dalamnya mengikuti font halaman, bukan font default browser. font-size: 1rem atau lebih besar juga mencegah ponsel men-zoom saat input difokus.
Fokus yang terlihat adalah persyaratan aksesibilitas. Ganti border biasa dengan ring yang jelas:
input[type="text"]:focus,
input[type="email"]:focus,
textarea:focus,
select:focus {
outline: none;
border-color: #2563eb;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.2);
}
input:focus-visible {
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.3);
}Menghapus outline default tanpa pengganti adalah kesalahan umum. Pola ring (box-shadow) di sekitar border mempertahankan petunjuk fokus sekaligus tampil lebih modern daripada outline default.
Pseudo-class :valid dan :invalid merespons validasi bawaan browser:
input:invalid {
border-color: #dc2626;
}
input:invalid:focus {
box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.2);
}
input:valid {
border-color: #16a34a;
}
input::placeholder {
color: #94a3b8;
opacity: 1;
}Kontrol dengan atribut required, type, atau pattern otomatis berstatus valid atau invalid. Menggabungkan :invalid dengan :focus memberi umpan balik saat pengguna masih mengetik, bukan menyalakan merah sejak halaman dimuat. ::placeholder menata teks petunjuk yang sering terlalu pucat di browser.
Checkbox, radio, dan range menyulitkan styling penuh. accent-color mewarnai kontrol native dalam satu baris:
.selesai { accent-color: #2563eb; }
.form-periksa { display: grid; gap: 12px; }
.periksa { display: flex; align-items: center; gap: 10px; }
.periksa input { width: 18px; height: 18px; }accent-color mengubah warna centang, isi radio, dan pengisi range mengikuti palet kalian tanpa menata ulang seluruh kontrol. Untuk ukuran yang lebih besar, perbesar kotak checkbox dan area klik dengan padding.
<label class="periksa">
<input type="checkbox" name="setuju" checked>
<span>Saya menyetujui ketentuan layanan</span>
</label>Bungkus input di dalam label agar teks ikut menjadi target klik. Kontrol yang mudah diklik mempercepat pengisian form secara signifikan.
select bisa diberi padding, border, dan font agar selaras:
select {
padding: 10px 36px 10px 12px;
border: 1px solid #cbd5e1;
border-radius: 8px;
font-size: 1rem;
font-family: inherit;
background-color: white;
color: #0f172a;
appearance: none;
}appearance: none menghapus panah bawaan browser. Bila kalian menghapusnya, sediakan panah pengganti — misalnya ikon background CSS — agar pengguna tetap tahu kontrol ini bisa dibuka.
input[type="range"] {
width: 100%;
accent-color: #2563eb;
}
progress {
accent-color: #2563eb;
width: 100%;
}input[type="range"], progress, dan meter semuanya menerima accent-color. Untuk kebutuhan lanjutan seperti track khusus, gunakan pseudo-element ::-webkit-slider-thumb dan ::-moz-range-thumb dengan prefix per browser.
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Form Kontak</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<form class="form" novalidate>
<div class="kelompok">
<label for="nama">Nama</label>
<input id="nama" type="text" name="nama" placeholder="Nama lengkap" required>
</div>
<div class="kelompok">
<label for="email">Email</label>
<input id="email" type="email" name="email" placeholder="nama@email.com" required>
</div>
<div class="kelompok">
<label for="pesan">Pesan</label>
<textarea id="pesan" name="pesan" rows="4" required></textarea>
</div>
<label class="periksa">
<input type="checkbox" name="setuju">
<span>Izinkan saya menerima info terbaru</span>
</label>
<button class="tombol" type="submit">Kirim</button>
</form>
</body>
</html>* { box-sizing: border-box; }
body { margin: 0; padding: 32px; font-family: system-ui, sans-serif; background-color: #f1f5f9; }
.form { max-width: 480px; margin-inline: auto; padding: 24px; background-color: white; border-radius: 12px; box-shadow: 0 2px 8px rgba(15, 23, 42, 0.1); }
.kelompok { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
label { font-size: 0.9rem; font-weight: 600; }
input, textarea { padding: 10px 12px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 1rem; font-family: inherit; color: #0f172a; }
input:focus, textarea:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.2); }
.periksa { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.periksa input { width: 18px; height: 18px; accent-color: #2563eb; }
.tombol { width: 100%; padding: 12px; border: none; border-radius: 8px; background-color: #2563eb; color: white; font-size: 1rem; cursor: pointer; transition: background-color 0.2s ease; }
.tombol:hover { background-color: #1d4ed8; }Jalankan npx serve . lalu klik ke dalam setiap input. Ring biru menunjukkan posisi fokus, dan kontrol accent-color menyelaraskan checkbox dengan tombol. Uji dengan menekan Tab untuk memastikan urutan fokus masuk akal.
Placeholder menghilang saat pengguna mengetik dan kontrasnya rendah. Selalu gunakan elemen label terpisah yang tetap terlihat.
Warna merah saja tidak cukup — pengguna buta warna kesulitan membedakannya. Tambahkan teks error dan ikon selain perubahan warna.
Menghapus outline default tanpa ring pengganti membuat navigasi keyboard kehilangan petunjuk. Pastikan setiap kontrol punya state fokus yang terlihat.
Inti yang harus dibawa pulang:
:valid dan :invalid memberi umpan balik validasi tanpa JavaScript.accent-color mewarnai checkbox, radio, dan range dalam satu baris.appearance: none memerlukan pengganti panah pada select.