HTML formları, kullanıcıdan veri toplamanın en yaygın yoludur. Ancak “çalışan bir form” ile “kolay doldurulan, anlaşılır hatalar veren ve erişilebilir bir form” arasında büyük fark vardır. Bu yazıda, kodlama yapısı örnekleri üzerinden üç ana konuyu birlikte ele alacağız: doğru giriş alanı türlerini seçme (input types), yerleşik form doğrulaması (form validation) ve erişilebilir etiketleme (ARIA nitelikleri).
Not: Tarayıcıların yerleşik doğrulama mesajları ve bazı input davranışları değişkenlik gösterebilir. Kritik doğrulamaları her zaman sunucu tarafında da tekrar etmek iyi bir uygulamadır. MDN, HTML’nin yerleşik kısıt doğrulamasını ve Constraint Validation API’yi bu çerçevede anlatır. (MDN Constraint validation)
1) Doğru input türünü seçmek: veri kalitesi ve kullanıcı deneyimi
Birçok doğrulama ihtiyacını, JavaScript yazmadan sadece doğru type seçerek karşılayabilirsiniz. Örneğin type="email" e‑posta formatına dair temel bir kontrol sağlar ve mobil cihazlarda uygun klavyeyi açabilir. Benzer şekilde type="number" sayı girişi için tarayıcıya ipucu verir. (MDN <input>)
Yaygın input türleri ve ne zaman kullanılmalı?
| Tür | Ne için uygun? | Pratik not |
|---|---|---|
| text | Genel metin | Ek kısıtlar için minlength, maxlength, pattern ekleyin. |
| E‑posta adresi | Temel format kontrolü sağlar; yine de sunucuda doğrulayın. (MDN) | |
| tel | Telefon | Format ülkeye göre değişir; genelde pattern + açıklama metni gerekir. |
| url | Web adresi | Tarayıcı URL formatına dair kontrol yapabilir. |
| number | Sayı | min, max, step ile aralık belirleyin; tarayıcı farkları olabilir. |
| date | Tarih | Tarih seçici arayüz tarayıcıya göre değişebilir; düz metin alternatifleri düşünün. |
| password | Parola | minlength ve açıklayıcı yardım metni ekleyin; hata mesajlarını net tutun. |
Doğru alan adı (name) ve autocomplete: “görünmeyen” kalite artışı
Form alanlarınızın name değerleri sunucu tarafı işleme için önemlidir. Ayrıca autocomplete ipuçları (ör. email, given-name) uygun senaryolarda kullanıcıların formu daha hızlı doldurmasına yardımcı olabilir. Yine de otomatik doldurmayı her senaryoda varsaymak doğru değildir (ör. paylaşımlı cihazlar).
2) Yerleşik doğrulama (Constraint Validation): required, pattern ve diğerleri
HTML, form kontrolleri için “kısıt doğrulama” (constraint validation) adı verilen bir sistem sunar. Bu sistem, alan türüne bağlı kontrolleri (ör. email formatı) ve niteliklerle eklediğiniz kısıtları (required, minlength, pattern gibi) birlikte değerlendirir. (MDN Constraint validation)
En kullanışlı doğrulama nitelikleri
- required: Alan boş bırakılamaz.
- minlength / maxlength: Metin uzunluğu sınırı.
- min / max / step: Sayısal aralık ve adım.
- pattern: Düzenli ifade ile biçim kısıtı (özellikle text/tel için).
pattern kullanırken kullanıcıya yardımcı olma
pattern güçlüdür, ancak kullanıcı “hangi formatı” beklediğinizi anlayamazsa hata mesajı döngüsü oluşur. Bu yüzden pattern ile birlikte kısa bir açıklama metni vermek ve bunu aria-describedby ile alana bağlamak iyi bir yaklaşımdır. WebAIM, yardım metinleri ve açıklamaların kullanıcıya programatik olarak iliştirilmesini önerir. (WebAIM Accessible Forms)
Aşağıdaki örnek, ABD odaklı bir posta kodu formatını (5 haneli veya 5+4) hedefler. Bu bir “örnek”tir; gerçek ürününüzde hedeflediğiniz ülkeye göre kuralı netleştirin.
<label for="zip">ZIP Code</label>
<input id="zip" name="zip" type="text" inputmode="numeric"
required pattern="^\d{5}(-\d{4})?$" aria-describedby="zip_help">
<p id="zip_help">Format: 12345 veya 12345-6789</p>
İpucu: inputmode gibi ipuçları klavye deneyimini iyileştirebilir; doğrulama mantığı yerine geçmez.
Yerleşik doğrulama mesajları neden tek başına yeterli değildir?
- Tarayıcılar hata mesajlarını farklı metinlerle ve farklı zamanlarda gösterebilir. (MDN)
- Mesajlar yerelleştirilebilir; ürününüz Türkçe olsa bile kullanıcı İngilizce tarayıcı kullanıyor olabilir.
- Sunucu tarafında aynı kuralları uygulamazsanız veri kalitesi düşer (ve bazı durumlarda iş mantığınız bozulabilir).
3) Constraint Validation API: özel hata mesajı ve kontrollü akış
HTML’nin yerleşik doğrulaması çoğu durumda yeterlidir; ama bazen özel hata mesajı göstermek, birden fazla alanı birlikte değerlendirmek veya hata anında odak yönetimi yapmak istersiniz. MDN, bunun için Constraint Validation API’nin temel yöntemlerini öne çıkarır: checkValidity(), reportValidity() ve setCustomValidity(). (MDN Constraint Validation API)
Temel yöntemler ne işe yarar?
- checkValidity(): Alan/forma ait kurallar geçerli mi diye kontrol eder; görsel mesaj göstermeyebilir.
- reportValidity(): Geçerli değilse tarayıcının yerleşik hata arayüzünü tetikleyebilir.
- setCustomValidity(message): Kendi hata mesajınızı atar (boş string verirseniz özel hata kalkar).
Örnek: parola kurallarını kullanıcı dostu mesajla anlatmak
Aşağıdaki JavaScript parçası, “en az 12 karakter” gibi bir kuralı kullanıcıya net bir mesajla iletmek için setCustomValidity kullanır. Bu kodu genellikle ayrı bir JS dosyasında ya da sayfada uygun bir yerde çalıştırırsınız (bu yazıda sadece örnek olarak metin şeklinde veriliyor).
const password = document.querySelector('#password');
password.addEventListener('input', () => {
if (password.value.length < 12) {
password.setCustomValidity('Parola en az 12 karakter olmalı.');
} else {
password.setCustomValidity('');
}
});
Bu yaklaşımın avantajı, tarayıcıya “geçersiz” durumunu standart mekanizma üzerinden iletmesidir. Yani alanın validity durumu değişir ve form gönderimi engellenebilir. (MDN)
Ne zaman novalidate kullanılır?
Bazen tüm doğrulamayı kendiniz yönetmek istersiniz. Bu durumda form üzerinde novalidate kullanarak tarayıcı yerleşik doğrulamasını devre dışı bırakabilirsiniz. Ancak bu, erişilebilir hata mesajları ve odak yönetimi sorumluluğunu tamamen size taşır. Yerleşik doğrulama ile başlamanız, sonra ihtiyaç oldukça API ile zenginleştirmeniz çoğu ekip için daha güvenli bir yoldur.
4) Erişilebilirlik temeli: önce label, sonra gerekirse ARIA
Form erişilebilirliğinde en kritik konu, her kontrolün programatik olarak iliştirilmiş bir etikete sahip olmasıdır. W3C’nin WAI-ARIA Authoring Practices dokümanı ve WebAIM rehberi, mümkün olduğunda görünür label kullanımını öncelikli yaklaşım olarak ele alır. Çünkü label hem ekran okuyucuya isim sağlar hem de tıklanabilir alanı büyütebilir. (WAI-ARIA APG 1.2) (WebAIM)
Doğru label bağlama: for + id
<label for="email">E-posta</label>
<input id="email" name="email" type="email" autocomplete="email" required>
Placeholder neden etiket yerine geçmez?
Placeholder metni, kullanıcı yazmaya başladığında kaybolur ve kalıcı bir alan adı (label) gibi davranmaz. Ayrıca placeholder’ın bir “etiket” gibi yardımcı teknolojiler tarafından duyurulması bazı kombinasyonlarda mümkün olsa da bu davranış tutarlı ve güvenilir değildir; bu yüzden erişilebilir adlandırma için placeholder’a güvenmek doğru değildir. MDN ve WebAIM, placeholder’ın etiket yerine kullanılmaması gerektiği konusunda uyarır. (MDN <input>) (WebAIM)
Placeholder’ı, ancak etikete ek bir örnek vermek için (örn. “name@example.com”) destekleyici unsur olarak düşünün.
ARIA’yı ne zaman kullanmalı? (aria-label, aria-labelledby, aria-describedby)
- aria-label: Görsel etiketin olmadığı (ve tasarımsal olarak olamayacağı) nadir durumlarda kısa bir isim vermek için.
- aria-labelledby: Alan adını sayfadaki mevcut bir metinden (başlık, satır adı gibi) türetmek için.
- aria-describedby: Yardım metni, format açıklaması veya hata açıklamasını alana bağlamak için.
Önemli: ARIA “ek güç” gibi görünse de yanlış kullanımı yeni erişilebilirlik sorunları yaratabilir. Bu nedenle önce semantik HTML (label, doğru type, doğru name) ve ancak gerektiğinde ARIA yaklaşımı daha sürdürülebilirdir. (WebAIM) (WAI-ARIA APG)
Örnek: yardım metni ve hata metnini aria-describedby ile iliştirmek
Aşağıdaki yapıda, yardım metni her zaman okunabilir; hata metni ise JS ile doldurulabilir. (Hata metnini nasıl yöneteceğiniz tasarımınıza bağlıdır; önemli olan ilişkilendirmedir.)
<label for="phone">Telefon</label>
<input id="phone" name="phone" type="tel"
aria-describedby="phone_help phone_error"
pattern="^\+?1?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$">
<p id="phone_help">Örnek: (555) 123-4567</p>
<p id="phone_error"></p>
Bu pattern, belirli ABD telefon yazımlarını hedefleyen bir örnektir; gerçek dünyada daha esnek kabul kriterleri gerekebilir. Her durumda, format beklentinizi yardım metninde açıkça söyleyin.
5) Uçtan uca örnek: erişilebilir ve doğrulamalı basit kayıt formu
Aşağıdaki örnek, yerleşik doğrulama niteliklerini ve etiketleme en iyi uygulamalarını bir araya getirir. Üretimde, sunucu tarafında da aynı kontrolleri uygulamayı ve hata metinlerini tutarlı bir dille sunmayı planlayın.
<form action="https://example.com/signup" method="post">
<h3>Hesap oluştur</h3>
<label for="first_name">Ad</label>
<input id="first_name" name="first_name" type="text"
autocomplete="given-name" required minlength="2">
<label for="email">E-posta</label>
<input id="email" name="email" type="email"
autocomplete="email" required>
<label for="password">Parola</label>
<input id="password" name="password" type="password"
required minlength="12" aria-describedby="pw_help">
<p id="pw_help">En az 12 karakter. Mümkünse uzun bir parola cümlesi kullanın.</p>
<label for="tos">
<input id="tos" name="tos" type="checkbox" required>
Şartları kabul ediyorum
</label>
<p>Gönder butonu ve tasarım öğeleri ürününüze göre eklenmelidir.</p>
</form>
Örnek URL, sadece gösterim amaçlıdır. Kendi uygulamanızda, gönderim endpoint’inizi ve CSRF gibi güvenlik gereksinimlerinizi çerçevenize uygun şekilde ele alın.
6) Tarayıcı farklılıkları ve test kontrol listesi
MDN, yerleşik doğrulama mesajlarının ve bazı input davranışlarının tarayıcılar arasında değişebildiğini belirtir. Bu yüzden “bende çalışıyor” yeterli bir kriter değildir. (MDN <input>) (MDN Constraint validation)
Hızlı test kontrol listesi
- En az iki tarayıcı: Chrome + Firefox (ve mümkünse Safari) ile aynı senaryoları deneyin.
- Klavye ile kullanım: Tab sırası mantıklı mı? Odak görünür mü? Alanlar doğru sırada mı?
- Ekran okuyucu duman testi: Alan adları okunuyor mu? Yardım metni (aria-describedby) alanla birlikte anılıyor mu?
- Hata senaryoları: Boş required alan, pattern ihlali, kısa parola gibi durumlarda kullanıcı ne yapacağını anlıyor mu?
- Mobil klavye: email/tel/number gibi type’lar doğru klavyeyi açıyor mu?
Sunucu tarafı doğrulama hatalarını nasıl yansıtmalı?
Yerleşik doğrulama, kullanıcı daha formu göndermeden birçok hatayı yakalayabilir; ama sunucudan dönen hata (ör. “bu e‑posta zaten kayıtlı”) gibi durumlar için de plan gerekir. Bu noktada:
- Hata mesajını ilgili alanın yakınına yerleştirin.
- Mesajı aria-describedby ile alana bağlayın (ve gerekiyorsa odağı hatalı alana taşıyın).
- Mesajın dili kısa, eyleme dönük ve teknik olmayan bir dille yazılmış olsun.
7) Sık sorulan sorular
required ve pattern birlikte nasıl çalışır?
Alan boşsa required kuralı ihlal edilir; alan doluysa bu kez değer pattern ile eşleşmek zorundadır. Bu mantık, HTML’nin yerleşik kısıt doğrulamasının (constraint validation) parçasıdır. (MDN)
setCustomValidity ne zaman kullanılır?
Tarayıcının varsayılan mesajı yetersiz kaldığında (ör. ürün diline uygun, daha açıklayıcı bir mesaj istediğinizde) veya birden fazla koşulu daha anlaşılır tek bir mesajla anlatmak istediğinizde setCustomValidity() kullanabilirsiniz. Mesajı temizlemek için boş string verilir. (MDN)
aria-label ile label arasında hangisini seçmeliyim?
Mümkünse görünür label tercih edilir; ARIA adlandırması (ör. aria-label) daha çok görünür etiketin tasarımsal olarak olamayacağı istisnai durumlar için düşünülmelidir. (WebAIM) (WAI-ARIA APG)
Sonuç: sürdürülebilir bir form mimarisi için kısa reçete
İyi bir HTML formu, sadece veri toplamaz; kullanıcıyı doğru alana yönlendirir, hatayı anlaşılır biçimde açıklar ve yardımcı teknolojilerle uyumlu çalışır. Başlangıç için şu sırayı izlemek genelde en verimli yaklaşımdır:
- Doğru input type seçin. (MDN)
- Yerleşik kısıtları (required, minlength, pattern) ekleyin. (MDN)
- Her alanı görünür label ile etiketleyin; placeholder’ı etiket yerine kullanmayın. (WebAIM)
- Yardım ve hata metinlerini aria-describedby ile iliştirin; ARIA’yı gerektiğinde kullanın. (WAI-ARIA APG)
- Gerektiğinde Constraint Validation API ile mesajları özelleştirin ve akışı kontrol edin. (MDN)
- Tarayıcı/cihaz farkları için mutlaka test edin ve sunucu tarafında doğrulamayı tekrarlayın.
Bu yaklaşım, bakım maliyetini düşürür ve kullanıcıların formu daha az sürtünmeyle tamamlamasına yardımcı olur.