HTML FORM ELEMANLARINI DOĞRU KULLANMAK
Her web tasarımcısı yıllar içinde aynı formu yüz kez yazar. Ad, e-posta, telefon, mesaj, gönder. Bu kadar tanıdık olmasına rağmen pratikte yapılan hatalar inanılmaz. Mobil klavyede telefon yazarken yanlış tuş takımı açılır; ekran okuyucu kullanıcısı label bağlanmamış input'u "metin alanı" diye duyar; otomatik doldurma çalışmaz; "Required" yazısı kırmızı bir noktaya gömülüdür.
Bu sorunların hiçbiri JavaScript ile çözülmez; çoğu HTML'in sunduğu native özellikleri yanlış veya hiç kullanmamaktan kaynaklanır. Doğru HTML formu daha az kod, daha iyi UX, daha güvenli, daha hızlı ve daha erişilebilirdir.
Input tipinden label bağlamaya, autocomplete'ten native validasyona — form kalitesini belirleyen şey büyük kütüphaneler değil, bu küçük ve çoğu zaman atlanan detaylardır. Erişilebilirlik ve mobil uyum da aynı detayların doğal ödülü olarak gelir.
Input Type — En Çok Kaçırılan Detay
HTML5 ile gelen input type'ları sadece görünüm değil, tüm bir kullanıcı deneyimini değiştirir.
| Type | Etki |
|---|---|
| text | Genel metin, varsayılan. |
| Mobil klavyede @ tuşu öne çıkar; native @ kontrolü yapar. | |
| tel | Mobil klavyede tuş takımı açılır; sadece rakam. |
| url | Mobil klavyede .com tuşu öne çıkar; URL şeması doğrulanır. |
| number | Mobil sayısal klavye, +/- butonları, min/max validasyon. |
| date | Native takvim picker'ı, çoğu tarayıcıda hazır. |
| time | Native saat seçici. |
| search | Mobil klavyede "Ara" butonu, browser geçmiş entegrasyonu. |
| password | Şifre maskesi, password manager entegrasyonu. |
| color | Native renk seçici. |
| file | Dosya seçici, accept attribute ile filtreleme. |
| checkbox / radio | Onay kutusu, tekli seçim. |
| range | Slider; min/max/step parametreleri. |
| hidden | Görünmez veri (genelde CSRF token, ID). |
Tüm input'ları type="text" yapmak HTML'i piyasaya 1996'da bırakıp 30 yıl geri gitmek demektir. Sadece type'ı doğru atayarak mobil dönüşümün ciddi yükseldiğini görebilirsin.

Label ve Input Bağlama
Her input bir label'la eşleşmeli. Tek bir label "Adınız" yazıp altına input koymak yetmez; bağlama HTML açısından gerçek olmalı.
<!-- DOĞRU -->
<label for="ad">Adınız</label>
<input type="text" id="ad" name="ad">
<!-- ALTERNATİF: nested -->
<label>
Adınız
<input type="text" name="ad">
</label>Faydaları:
- Label'a tıklayınca input focus alır (mobilde çok değerli).
- Ekran okuyucu label'ı input'la birlikte okur.
- Form validasyon hata mesajları doğru input'a bağlanır.
- CSS ile :focus + label ilişkisi kurabilirsiniz.
"Placeholder yeterli, label gerekmez" yaklaşımı yanlış. Placeholder yazı yazıldıkça kaybolur; kullanıcı ne alana yazdığını unutur. Erişilebilirlik açısından da yetersiz.
Placeholder — Doğru Kullanım
Placeholder yardımcı bir ipucu, etiket değildir. Kullanım ilkeleri:
- Label'ı asla yerini almasın.
- Örnek değer için kullan: "ornek@firma.com", "0532 123 45 67".
- Açıklama için değil; uzun açıklama input altında ayrı bir text olmalı.
- Soluk gri renk düşük kontrastlıdır; "büyük placeholder, soluk label" kombinasyonu erişilebilirliği bozar.
İyi label + iyi placeholder kombinasyonu kullanıcıya iki katman bilgi sunar: ne soruluyor (label), nasıl cevaplanacak (placeholder).
Autocomplete Attribute — Görünmez UX Kazancı
autocomplete attribute browser'ın hangi alanı nasıl otomatik dolduracağını söyler. Doğru kullanıldığında kullanıcı bilgi formunu 5 saniyede tamamlar; yanlış kullanıldığında her seferinde elle yazar.
<input type="text" name="firstName" autocomplete="given-name">
<input type="text" name="lastName" autocomplete="family-name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="text" name="address" autocomplete="street-address">
<input type="text" name="city" autocomplete="address-level2">
<input type="text" name="postal" autocomplete="postal-code">
<input type="text" name="country" autocomplete="country-name">
<!-- Ödeme alanları -->
<input type="text" name="ccNumber" autocomplete="cc-number">
<input type="text" name="ccExp" autocomplete="cc-exp">
<input type="text" name="ccCsc" autocomplete="cc-csc">
<!-- Şifre alanları -->
<input type="password" autocomplete="current-password">
<input type="password" autocomplete="new-password"> <!-- Yeni şifre oluşturmada -->autocomplete="off" yazmak güvenlik artırır zannıyla yapılır ama tam tersi etki yaratır; geçerli autocomplete değerlerinin tam listesini MDN web dokümantasyonu üzerinden görmek doğru token seçimini kolaylaştırır. Modern browser'lar zaten autocomplete="off"'u şifre alanlarında saygı göstermiyor.
Native Validation
HTML5 input'lara doğrudan validasyon kuralları koymanı sağlar — JavaScript yazmadan.
<input type="email" required>
<input type="tel" pattern="[0-9]{10,11}" required>
<input type="text" minlength="3" maxlength="50" required>
<input type="number" min="1" max="100" step="1">
<input type="password" minlength="8" required>Browser bu kurallara uymayan input'larda submit'i engelleyip native bir hata baloncuğu gösterir. Çevirisi otomatik olarak browser diline gelir.
Native validation tek başına yeterli değildir; server-side validation şart. Form yapımı, validasyon stratejileri ve erişilebilirlik kurallarını uçtan uca işleyen bir web tasarımı eğitimi bu disiplini pratiğe çevirir; client-side hızlı feedback için ekstra JS yazmak zorunda kalmazsın.
Hata Mesajları ve aria-describedby
Validation hata mesajları input'a görsel olarak değil semantik olarak da bağlanmalı:
<label for="email">E-posta</label>
<input
type="email"
id="email"
aria-describedby="email-error email-help"
aria-invalid="false"
required>
<p id="email-help">Örnek: ad@firma.com</p>
<p id="email-error" role="alert"></p>aria-describedby ile yardım metni ve hata mesajı input'a bağlanır. Ekran okuyucu input'a focus aldığında bu metinleri de okur. Hata oluştuğunda aria-invalid="true" yapılır ve hata p'sine mesaj eklenir.
Hata mesajı sade ve eylem odaklı olmalı: "E-posta zorunlu" değil, "E-posta adresinizi yazın". "Format yanlış" değil, "Geçerli bir e-posta yazın, örn. ad@firma.com".
Fieldset ve Legend
İlgili input grupları fieldset ile sarılmalı, başlığı legend ile verilmeli:
<fieldset>
<legend>İletişim bilgileri</legend>
<label for="ad">Ad</label>
<input id="ad" type="text">
<label for="email">E-posta</label>
<input id="email" type="email">
</fieldset>
<fieldset>
<legend>Adres</legend>
<!-- Adres alanları -->
</fieldset>Bu yapı uzun formları mantıksal bölümlere ayırır. Ekran okuyucu kullanıcısı her input'un hangi gruba ait olduğunu duyabilir. Radio grupları için özellikle önemli: aynı name ile birden çok radio fieldset+legend ile sarılmalı.
Mobil Optimizasyonu
Mobilde form deneyimi ayrı bir konu. Önemli detaylar:
- inputmode attribute: Type=text kalıp inputmode="numeric" demek mobil klavyenin sayısal açılmasını sağlar; doğrulama ve klavye ayrılır.
- enterkeyhint attribute: Klavyenin enter tuşunda yazıyı değiştir. "go", "search", "send", "next", "done" değerleri.
- Tek kolon düzeni: Mobilde yan yana input'lar küçük; alt alta tek kolon daha rahat.
- Yeterli boyut: Input touch target en az 44×44 px. Padding ile sağlanır.
- 16px font: Mobil Safari 16px altında font'lu input'a zoom yapar; UX bozulur. Min 16px tutmak gerekiyor.
Submit Butonu
Form butonu detayları kullanıcı deneyiminde belirleyici:
- Buton metni eyleme dönük: "Gönder" değil "Mesajı Gönder", "Hesap Aç", "Kaydı Tamamla".
- type="submit" açıkça belirtilmeli; default'ta button type="submit" varsayılır ama belirsizlik yaratmamak için yazılır.
- Form gönderilirken buton disabled olmalı; iki kere submit önlenir.
- Loading state görsel olarak belli edilmeli ("Gönderiliyor..." yazısı veya spinner).
- Başarılı submit sonrası mesaj veya sayfaya yönlendirme net olmalı.
Erişilebilirlik Kontrol Listesi
Form yayına almadan önce şu kontroller:
- Her input'un label'ı var ve for/id bağlantılı.
- Zorunlu alanlar required attribute'lu; sadece asterisk yazıyla işaretlemek yetmez.
- Hata mesajları aria-describedby ile bağlı.
- Klavye ile sırayla geçiş (Tab) anlamlı sırada gidiyor.
- Focus indicator görünür; outline'i kapatma.
- Renk tek başına bilgi vermiyor (kırmızı border + ikon + metin birlikte).
- Tüm form klavye ile doldurulup gönderilebiliyor.
- Ekran okuyucu (NVDA/VoiceOver) ile test edildi.

JavaScript Bağlama
HTML doğru kurulduktan sonra JavaScript hâlâ gerekli olabilir:
- Async submit (sayfa yenilenmeden form gönderimi).
- Detaylı validasyon (server'da check, password güçlülüğü).
- Conditional fields (bir seçeneğe bağlı diğer alanın görünmesi).
- Multistep forms (wizard akışı).
Ama temel HTML iskelet doğru kurulduğunda JS olmasa bile form çalışabilmeli (graceful degradation). Bu disiplinli yaklaşım daha hızlı, daha güvenli, daha erişilebilir formlar üretiyor; ve JS kodlama maliyetini ciddi şekilde düşürüyor.
Sonuç olarak iyi form HTML'i, az JS gerektiren HTML'dir. Her yeni form için kendine sormak iyi alışkanlık: "Bu davranış için JS gerek mi, yoksa HTML çoktan bunu sunuyor mu?" Çoğu zaman cevap HTML lehine. Kodun azaldıkça ürünün hem hızı hem kalitesi artar.



