---
title: "HTML5 formlar: input tipleri, doğrulama ve autocomplete rehberi"
author: "Abdulaziz Akyol"
author_url: https://www.abdulazizakyol.com/hakkimda/
url: https://www.abdulazizakyol.com/blog/html-5-form/
language: tr
published: 2018-10-01
updated: 2026-09-25
categories: ["HTML5", "Yazılım geliştirme"]
tags: ["HTML5", "HTML Form", "Form Doğrulama", "Constraint Validation API", "autocomplete", "Erişilebilirlik"]
description: "HTML5 input tipleri, required/pattern/min/max doğrulaması, Constraint Validation API, autocomplete değerleri ve erişilebilir etiketleme; çalışır örneklerle."
---

# HTML5 formlar: input tipleri, doğrulama ve autocomplete rehberi

Yazar: [Abdulaziz Akyol](https://www.abdulazizakyol.com/hakkimda/) · 2018-10-01

## Öne çıkanlar

- HTML5 input tipleri (email, url, tel, number, date, range, color vb.) mobilde doğru klavyeyi açar ve bir kısmı tarayıcı içi doğrulama getirir; desteklenmeyen tip text alanına geri düşer.
- required, minlength, maxlength, min, max, step ve pattern öznitelikleri istemci tarafı doğrulama sağlar, ancak sunucu tarafı doğrulamanın yerini tutmaz.
- Constraint Validation API (validity, checkValidity, reportValidity, setCustomValidity) ile tarayıcının doğrulama motoru korunarak özel hata mesajları ve kurallar eklenebilir.
- autocomplete özniteliğine on/off yerine name, email, username, new-password, one-time-code gibi amaç değerleri vermek hem otomatik doldurmayı düzeltir hem de WCAG 1.3.5 gereğini karşılar.
- keygen öğesi HTML standardından kaldırılmıştır; kimlik doğrulama için WebAuthn (passkey), anahtar üretimi için Web Crypto API kullanılır.

HTML5 formları, kullanıcıdan veri almak için gereken girdi tiplerini, doğrulama kurallarını ve otomatik doldurma ipuçlarını doğrudan HTML'e taşır. Doğru tipi ve öznitelikleri seçtiğinizde tarayıcı mobilde uygun klavyeyi açar, hatalı girişi gönderimden önce yakalar ve kayıtlı adres ya da parolaları doğru alanlara doldurur; üstelik bunların çoğu için tek satır JavaScript gerekmez.

Bu rehber, 2018'de yazdığım altı ayrı form notunun birleştirilmiş ve düzeltilmiş hâlidir. Eski notlarda başlıktaki "HTLM" yazım hatasından `type="name"` gibi var olmayan bir tipe, `multipart/formdata` gibi hatalı değerlerden standarttan çıkarılmış `<keygen>` öğesine kadar düzeltilmesi gereken çok şey vardı. Serinin genel çerçevesi için [HTML5 nedir?](https://www.abdulazizakyol.com/blog/html5-nedir/) yazısına bakabilirsiniz.

## Bir formun temel yapısı nasıl olmalı?

```html
<form action="/iletisim" method="post">
  <p>
    <label for="ad">Ad soyad</label>
    <input id="ad" name="ad" type="text" autocomplete="name" required>
  </p>
  <p>
    <label for="eposta">E-posta</label>
    <input id="eposta" name="eposta" type="email" autocomplete="email" required>
  </p>
  <button type="submit">Gönder</button>
</form>
```

Üç kural her şeyin temelidir. `name` olmayan alan sunucuya gönderilmez. `id` ile `<label for>` eşleşmesi alanın erişilebilir adını verir ve etikete tıklayınca alana odaklanılmasını sağlar. `method="post"`, verinin adres satırında görünmemesi ve değişiklik yapan istekler içindir; arama gibi paylaşılabilir sorgularda `get` uygundur.

## HTML5 hangi input tiplerini getirdi?

| Tip                              | Ne için                  | Not                                                                |
| -------------------------------- | ------------------------ | ------------------------------------------------------------------ |
| `email`                          | E-posta adresi           | Biçim doğrulaması yapar; `multiple` ile virgüllü liste kabul eder. |
| `url`                            | Web adresi               | Şema (`https://`) içermeyen değeri geçersiz sayar.                 |
| `tel`                            | Telefon                  | Biçim doğrulaması **yapmaz**; yalnızca telefon klavyesi açar.      |
| `number`                         | Adet, miktar             | Telefon, posta kodu ya da kart numarası için uygun değildir.       |
| `range`                          | Kesinliği önemsiz aralık | Kaydırıcı; seçilen değeri ayrıca göstermek gerekir.                |
| `date`, `time`, `datetime-local` | Tarih ve saat            | Değer her zaman `2026-09-25`, `14:30` gibi standart biçimdedir.    |
| `month`, `week`                  | Ay, hafta                | Firefox ve Safari masaüstünde desteklenmez, düz metne geri düşer.  |
| `color`                          | Renk seçici              | Değer `#rrggbb` biçimindedir.                                      |
| `search`                         | Arama kutusu             | Bazı tarayıcılarda temizleme düğmesi ekler.                        |

Eski notlarımdaki `datetime` tipi standarttan çıkarıldı; yerine `datetime-local` kullanılır. Tarayıcının tanımadığı her tip hata vermeden `text` gibi davranır, bu yüzden `month` ve `week` kullanıyorsanız sunucu tarafında biçimi mutlaka denetleyin.

```html
<label>Renk <input type="color" name="renk" value="#0b5fff"></label>
<label>Tarih <input type="date" name="tarih" min="2026-01-01" max="2026-12-31"></label>
<label>Saat <input type="time" name="saat" step="900"></label>
<label>Randevu <input type="datetime-local" name="randevu"></label>
<label>Adet <input type="number" name="adet" min="1" max="5" value="3"></label>
<label>Puan <input type="range" name="puan" min="0" max="10" value="5"></label>
<label>Web adresi <input type="url" name="site" placeholder="https://ornek.com"></label>
<label>Telefon <input type="tel" name="telefon" autocomplete="tel"></label>
<label>Belgeler <input type="file" name="belgeler" accept=".pdf,image/*" multiple></label>
```

`time` alanındaki `step="900"` değeri saniye cinsindendir ve 15 dakikalık adımlar tanımlar. Rakamlardan oluşan ama sayı olmayan veriler (posta kodu, doğrulama kodu, kart numarası) için `type="text"` ile `inputmode="numeric"` kullanın: sayısal klavye açılır ama baştaki sıfır silinmez, fare tekerleği değeri değiştirmez.

## Form dışındaki alanlar ve gönder düğmesi öznitelikleri

`form` özniteliği, `<form>` etiketinin dışındaki bir alanı forma bağlar. Eski notumda birden fazla form kimliğinin virgülle yazılabileceği söyleniyordu; bu yanlış, öznitelik **tek** bir form `id`'si alır.

Gönder düğmeleri ise formun ayarlarını yalnızca kendileri için geçersiz kılabilir:

```html
<form id="profil" action="/profil/kaydet" method="post">
  <label for="ad2">Ad</label>
  <input id="ad2" name="ad" required>

  <button type="submit">Kaydet</button>
  <button type="submit" formaction="/profil/taslak" formnovalidate>Taslak olarak kaydet</button>
  <button type="submit" formaction="/profil/onizle" formmethod="get" formtarget="_blank">Önizle</button>
</form>

<!-- Formun dışında ama form="profil" sayesinde onunla gönderilir -->
<label for="soyad2">Soyad</label>
<input id="soyad2" name="soyad" form="profil">
```

- **`formaction`**: Gönderim adresini değiştirir.
- **`formmethod`**: `get`, `post` ya da `dialog`.
- **`formenctype`**: Kodlama türü; dosya yüklemede `multipart/form-data` olmalıdır ve yalnızca `post` ile anlam taşır.
- **`formnovalidate`**: Bu düğmeyle gönderimde doğrulamayı atlar; taslak kaydetme için idealdir. Formun tamamında kapatmak için `<form novalidate>` kullanılır.
- **`formtarget`**: Yanıtın açılacağı pencere; yeni sekme için `_blank`.

`type="image"` bir görseli gönder düğmesi olarak kullanır; `alt`, `width` ve `height` ile birlikte yazılmalıdır.

## datalist, output ve kaldırılan keygen

`<datalist>`, bir metin alanına öneri listesi ekler. `<select>`'ten farkı, kullanıcının listede olmayan bir değer de yazabilmesidir; yani geçerli değerleri sunucuda yine denetlemeniz gerekir.

```html
<label for="sehir">Şehir</label>
<input id="sehir" name="sehir" list="sehirler">
<datalist id="sehirler">
  <option value="Ankara"></option>
  <option value="İstanbul"></option>
  <option value="İzmir"></option>
  <option value="Kocaeli"></option>
</datalist>
```

`<output>`, bir hesaplamanın sonucunu gösterir ve `for` özniteliğiyle girdilerine bağlanır. Satır içi `oninput` yerine olay dinleyici kullanmak daha temizdir:

```html
<form id="hesap">
  <input type="number" id="a" name="a" value="50"> +
  <input type="number" id="b" name="b" value="51"> =
  <output name="sonuc" for="a b">101</output>
</form>
<script>
  const hesap = document.getElementById("hesap");
  hesap.addEventListener("input", () => {
    const { a, b, sonuc } = hesap.elements;
    sonuc.value = (a.valueAsNumber || 0) + (b.valueAsNumber || 0);
  });
</script>
```

`<keygen>` ise tarayıcıda anahtar çifti üretip açık anahtarı formla göndermek için tasarlanmıştı. Standarttan çıkarıldı; Chrome öğeyi tanınmayan öğeye dönüştürdü, Firefox 69 sürümünde tamamen kaldırdı. Bugün kimlik doğrulama için WebAuthn tabanlı passkey'ler, anahtar üretimi için Web Crypto API kullanılır.

## Doğrulama öznitelikleri nasıl çalışır?

| Öznitelik                | Uygulandığı yer                                    | Hata durumu (`validity`)          |
| ------------------------ | -------------------------------------------------- | --------------------------------- |
| `required`               | Çoğu alan                                          | `valueMissing`                    |
| `type` (`email`, `url`)  | İlgili tipler                                      | `typeMismatch`                    |
| `minlength`, `maxlength` | Metin alanları                                     | `tooShort`, `tooLong`             |
| `min`, `max`             | Sayı, tarih, saat, `range`                         | `rangeUnderflow`, `rangeOverflow` |
| `step`                   | Sayı, tarih, saat, `range`                         | `stepMismatch`                    |
| `pattern`                | Metin, `tel`, `email`, `url`, `search`, `password` | `patternMismatch`                 |

```html
<form action="/kayit" method="post">
  <label for="kullanici">Kullanıcı adı</label>
  <input id="kullanici" name="kullanici" required minlength="3" maxlength="20"
         pattern="[a-z0-9_]+" autocomplete="username"
         aria-describedby="kullanici-ipucu">
  <p id="kullanici-ipucu">3–20 karakter; küçük harf, rakam ve alt çizgi.</p>

  <label for="gsm">Cep telefonu (başında 0 olmadan)</label>
  <input id="gsm" name="gsm" type="tel" pattern="5[0-9]{9}" autocomplete="tel-national">

  <label for="posta-kodu">Posta kodu</label>
  <input id="posta-kodu" name="posta_kodu" inputmode="numeric" pattern="[0-9]{5}"
         autocomplete="postal-code">

  <label for="tutar">Tutar (TL)</label>
  <input id="tutar" name="tutar" type="number" min="0" step="0.01">

  <button type="submit">Kaydol</button>
</form>
```

`pattern` hakkında bilinmesi gerekenler:

- Desen **tüm değeri** eşlemelidir; başına `^` sonuna `$` yazmanıza gerek yoktur.
- [MDN'e göre](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/pattern) desen, 2023'ten beri JavaScript'in `v` bayrağıyla derleniyor. Bu yüzden köşeli parantez sınıfı içinde tire gibi karakterleri kaçış karakteriyle yazın: `[a-z\-]`.
- Ad soyad alanlarını desenle kısıtlamayın. Eski notumdaki `[A-Za-z]{2,}` deseni "Şükrü" ya da "Güneş" adlarını reddediyordu.

`number` alanında `step` varsayılan olarak 1'dir; ondalıklı değer kabul etmek için `step="0.01"` ya da `step="any"` verin. İstemci doğrulaması yalnızca kullanıcı deneyimi içindir; tarayıcıyı atlayan bir istek bu kuralların hiçbirine takılmaz, aynı kontrolleri sunucuda da yapın.

## Constraint Validation API ile özel doğrulama

Tarayıcının doğrulama motoru JavaScript'ten de yönetilebilir ([MDN: Constraint validation](https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation)). Her alanın `validity` nesnesi yukarıdaki tablodaki durumları, `validationMessage` tarayıcının mesajını verir. `checkValidity()` sessizce denetler, `reportValidity()` hata balonunu gösterir, `setCustomValidity("mesaj")` özel bir kural ekler ve boş metinle çağrılınca hatayı temizler.

Aşağıdaki örnek parola tekrarını denetler, hataları alanın altında gösterir ve ilk hatalı alana odaklanır:

```html
<form id="kayit" action="/kayit" method="post" novalidate>
  <label for="parola">Parola</label>
  <input id="parola" name="parola" type="password" autocomplete="new-password"
         required minlength="12" aria-describedby="parola-hata">
  <p id="parola-hata" aria-live="polite"></p>

  <label for="parola2">Parola (tekrar)</label>
  <input id="parola2" name="parola2" type="password" autocomplete="new-password"
         required aria-describedby="parola2-hata">
  <p id="parola2-hata" aria-live="polite"></p>

  <button type="submit">Hesap oluştur</button>
</form>
```

```javascript
const form = document.getElementById("kayit");
const { parola, parola2 } = form.elements;

function eslesmeyiKontrolEt() {
  const hata = parola2.value && parola2.value !== parola.value;
  parola2.setCustomValidity(hata ? "Parolalar eşleşmiyor." : "");
}

function hataGoster(alan) {
  const kutu = document.getElementById(`${alan.id}-hata`);
  if (alan.validity.valid) {
    alan.removeAttribute("aria-invalid");
    kutu.textContent = "";
    return;
  }
  alan.setAttribute("aria-invalid", "true");
  if (alan.validity.valueMissing) {
    kutu.textContent = "Bu alan zorunludur.";
  } else if (alan.validity.tooShort) {
    kutu.textContent = `En az ${alan.minLength} karakter girin.`;
  } else {
    kutu.textContent = alan.validationMessage;
  }
}

parola.addEventListener("input", eslesmeyiKontrolEt);
parola2.addEventListener("input", eslesmeyiKontrolEt);
for (const alan of [parola, parola2]) {
  alan.addEventListener("blur", () => hataGoster(alan));
}

form.addEventListener("submit", (olay) => {
  eslesmeyiKontrolEt();
  if (!form.checkValidity()) {
    olay.preventDefault();
    [parola, parola2].forEach(hataGoster);
    form.querySelector("[aria-invalid='true']")?.focus();
  }
});
```

`novalidate` tarayıcının kendi hata balonlarını kapatır ama doğrulama motorunu kapatmaz; `validity` ve `checkValidity()` çalışmaya devam eder. Yalnızca CSS ile görsel geri bildirim istiyorsanız, kullanıcı alanla etkileşime girmeden hata göstermeyen `:user-invalid` sözde sınıfını kullanın (MDN'e göre Kasım 2023'ten beri tüm büyük tarayıcılarda çalışıyor):

```css
input:user-invalid {
  border-color: #b00020;
  outline: 2px solid #b00020;
}
```

## autocomplete ile otomatik doldurmayı doğru yönlendirmek

Eski notlarımda `autocomplete` yalnızca `on` ve `off` değerleriyle anlatılmıştı. Asıl güç, alanın **amacını** bildiren değerlerdedir:

| Değer                                           | Ne için                                                      |
| ----------------------------------------------- | ------------------------------------------------------------ |
| `name`, `given-name`, `family-name`             | Ad soyad, ad, soyad                                          |
| `email`, `tel`, `tel-national`                  | E-posta, telefon, ülke kodsuz telefon                        |
| `username`                                      | Giriş kimliği                                                |
| `current-password`                              | Giriş formundaki mevcut parola                               |
| `new-password`                                  | Kayıt ve parola değiştirme; tarayıcı güçlü parola önerebilir |
| `one-time-code`                                 | SMS ya da e-postayla gelen tek kullanımlık kod               |
| `organization`                                  | Şirket adı                                                   |
| `street-address`, `postal-code`, `country-name` | Adres, posta kodu, ülke adı                                  |
| `bday`                                          | Doğum tarihi                                                 |
| `cc-name`, `cc-number`, `cc-exp`, `cc-csc`      | Kart bilgileri                                               |

```html
<label>Doğrulama kodu
  <input name="kod" inputmode="numeric" autocomplete="one-time-code" maxlength="6">
</label>
<label>Teslimat adresi
  <textarea name="teslimat_adres" autocomplete="shipping street-address"></textarea>
</label>
<label>Fatura posta kodu
  <input name="fatura_posta" autocomplete="billing postal-code">
</label>
```

`shipping` ve `billing` önekleri iki adresi ayırır; aynı sayfada iki kişinin bilgisi varsa `section-` ile başlayan bir grup adı eklenir. Passkey girişinde `autocomplete="username webauthn"` kullanılır. Modern tarayıcılar giriş formlarında `autocomplete="off"` değerini çoğunlukla yok sayar; kapatmaya çalışmak yerine doğru amaç değerini verin.

Bu değerler erişilebilirlik gereği de karşılar: WCAG 2.2'nin [1.3.5 "Girdi Amacını Belirleme"](https://www.w3.org/WAI/WCAG22/Understanding/identify-input-purpose.html) başarı ölçütü (AA), kullanıcıya ait bilgileri isteyen alanların amacının programatik olarak belirlenmesini ister.

## Erişilebilir etiketleme için kurallar

- **Her alanın görünür bir `<label>`'ı olsun.** `placeholder` etiket değildir: yazmaya başlayınca kaybolur, kontrastı çoğu zaman düşüktür.
- **İlgili seçenekleri `<fieldset>` ve `<legend>` ile gruplayın.** Ekran okuyucu her seçenekte grubun sorusunu da okur.
- **İpucu ve hata metnini `aria-describedby` ile bağlayın**; hatalı alana `aria-invalid="true"` verin.
- **Hatayı yalnızca renkle göstermeyin**; metinle açıklayın (WCAG 1.4.1 ve 3.3.1).
- **Parola alanında yapıştırmayı engellemeyin.** Parola yöneticilerinin çalışabilmesi WCAG 2.2'deki 3.3.8 "Erişilebilir Kimlik Doğrulama" ölçütüyle de uyumludur.

```html
<fieldset>
  <legend>Teslimat yöntemi</legend>
  <label><input type="radio" name="teslimat" value="kargo" checked> Kargo</label>
  <label><input type="radio" name="teslimat" value="magaza"> Mağazadan teslim</label>
</fieldset>
```

Sayfa düzeyindeki yapı için [HTML5 anlamsal etiketler rehberindeki](https://www.abdulazizakyol.com/blog/html-5-anlamsal-web/) `<search>` ve landmark bölümüne, onay pencereleri için aynı rehberdeki `<dialog>` örneğine bakabilirsiniz. Formdan yüklenen görselleri önizlemek için [Canvas rehberindeki](https://www.abdulazizakyol.com/blog/html-5-grafik-islemlericanvas/) `drawImage` bölümüne, video ve ses dosyalarını sayfada oynatmak için [HTML5 video ve audio rehberine](https://www.abdulazizakyol.com/blog/html5-medya-etiketleri/) bakabilirsiniz.

## Kontrol listesi

- [ ] Her alanın `name` değeri ve `<label for>` ile bağlı görünür etiketi var.
- [ ] Tipler amaca göre seçildi: telefon `tel`, rakamlı kodlar `text` + `inputmode="numeric"`, tarih `date`.
- [ ] Doğrulama kuralları hem HTML özniteliklerinde hem sunucuda aynı.
- [ ] Kişisel veri alanlarında doğru `autocomplete` değerleri var; giriş ve kayıt formlarında `current-password` / `new-password` ayrımı yapıldı.
- [ ] Hata mesajları metin olarak, alana `aria-describedby` ile bağlı; gönderimde ilk hatalı alana odaklanılıyor.

## Sık sorulan sorular

### HTML5 form doğrulaması yeterli mi?

Hayır. Tarayıcı doğrulaması kullanıcıya hızlı geri bildirim vermek içindir; geliştirici araçlarıyla ya da doğrudan HTTP isteğiyle kolayca atlanabilir. Aynı kuralları sunucu tarafında mutlaka yeniden uygulayın.

### autocomplete off neden çalışmıyor?

Modern tarayıcılar, parola yöneticisinin giriş formlarını doldurmasını kullanıcı yararına kabul eder ve bu alanlarda autocomplete off değerini çoğunlukla yok sayar. Otomatik doldurmayı kapatmak yerine alanın amacını doğru değerle (current-password, new-password, one-time-code) bildirmek daha iyi sonuç verir.

### Telefon numarası için input type number mı kullanılmalı?

Hayır. number tipi ok tuşlarıyla artırma, baştaki sıfırı silme ve kaydırma tekerleğiyle değer değiştirme gibi sayısal davranışlar getirir. Telefon için type tel, posta kodu ve kart numarası gibi rakamlı kodlar için type text ile inputmode numeric kullanın.

### keygen etiketi yerine ne kullanılır?

keygen standarttan kaldırıldı ve güncel tarayıcılarda çalışmıyor. Kullanıcı kimlik doğrulaması için WebAuthn tabanlı passkey'ler, tarayıcıda anahtar çifti üretmek için Web Crypto API'nin generateKey yöntemi kullanılır.

## Kaynaklar

1. [WHATWG HTML Standard — Forms](https://html.spec.whatwg.org/multipage/forms.html)
2. [WHATWG HTML Standard — Autofill (autocomplete değerleri)](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html)
3. [MDN — Constraint validation](https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation)
4. [MDN — HTML autocomplete attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete)
5. [MDN — HTML pattern attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/pattern)
6. [W3C — Understanding WCAG 2.2 SC 1.3.5 Identify Input Purpose](https://www.w3.org/WAI/WCAG22/Understanding/identify-input-purpose.html)

---

Abdulaziz Akyol, CX Teknoloji'nin (yapay zekâ, görüntü işleme ve IoT) kurucusudur. Asıl sürüm: https://www.abdulazizakyol.com/blog/html-5-form/
