İçeriğe geç

Erişilebilirlik Temelleri — Gözü Kapalı Para Gönderebilir misin?

Başlangıç 9 dk Sık karşılaşılır

Önce şunu oku: Flexbox mı Grid mi — Telefonda Sayfa Neden Yana Kayıyor?

30 saniyede özet

Herkes sayfayı fareyle ve gözüyle kullanmıyor. Ekran okuyucu yalnızca HTML'in söylediğini okur: etiketsiz kutu adsızdır, div düğmeye Tab ile ulaşılmaz, kırmızı çerçeve hiç duyulmaz. Çoğu düzeltme tek bir doğru etikettir.

Bir arkadaşın sana telefonda bir formu okuyor ve sen ona söyleyerek dolduruyorsun. O yalnızca kâğıtta yazanı okuyabilir. Kâğıtta yazmayan bir şeyi, ne kadar renkli olursa olsun, sana anlatamaz.

  1. Bayt: Para gönderme formu hazır. Fareyle denedim, her şey çalışıyor.

  2. Sen: Klavyeyle denedin mi? Ya da ekran okuyucuyla?

  3. Bayt: Tab'a bastım, Gönder'e hiç gelmedi! Ekran okuyucu da tutar kutusuna 'düzenleme alanı' dedi, o kadar.

  4. Bayt: O zaman formu bir de kulakla ve klavyeyle gezelim.

Herkes fareyle gezmiyor

Bazı kullanıcılar sayfayı bir screen readerSayfayı sesli okuyan ya da Braille ekrana aktaran yazılım (NVDA, VoiceOver). Görüntüye değil, HTML'deki rol, ad ve duruma bakar.Sözlükte gör → ile dinler, bazıları yalnızca klavyeyle gezer. İkisi de ekrandaki görüntüye değil, HTML’in kendisine bakar.

Bu yüzden erişilebilirlik çoğu zaman ek bir iş değildir. Doğru HTML etiketini seçmek, işin büyük kısmını kendiliğinden yapar.

Kafam karıştı, daha basit anlat

Ekran okuyucu görüntüyü değil HTML’i okur. Doğru etiket, doğru okuma demektir.

Hızlı kontrolBaşlangıç

Ekran okuyucu bir sayfada neyi okur?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Klavyeyle gezen bir kullanıcı bir sonraki kontrole hangi tuşla geçer?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Önce doğru etiket

Gönder düğmesi bir div, üstünde onClick var ve fareyle sorunsuz çalışıyor. Klavyeyle Tab'a basarak ilerleyen biri bu düğmeye ulaşabilir mi? Cevabı göster

Hayır, çünkü div doğal olarak odaklanamaz ve bir rolü yoktur. Tab onun üstünden geçer, ekran okuyucu da onu düğme olarak tanıtmaz. Klavye kullanan biri parayı hiç gönderemez.

Telefondaki arkadaşın yalnızca kâğıtta yazanı okur.
Adım adım oku
  1. Etiketsiz kutu adsız okunur: ne istendiği bilinmez.
  2. Kırmızı çerçeve hiç duyulmaz: kullanıcı hatayı öğrenemez.
  3. div düğme atlanır: Tab orada durmaz, iş yapılamaz.
  4. Doğru etiketlerle her kontrol adıyla ve durumuyla okunur.

Bir kontrolün okunan adına accessible nameBir kontrolün ekran okuyucuda okunan adı. label for, düğmenin yazısı, aria-label ya da aria-labelledby'dan gelir.Sözlükte gör → denir. Kutunun yanındaki yazı bir span ise kutuya bağlı değildir; <label for> onu bağlar ve kutunun adı olur.

Tıklanan bir şey için <button> kullanmak, odaklanmayı, Enter ve Space ile çalışmayı ve “düğme” rolünü bedavaya getirir.

Kafam karıştı, daha basit anlat

Kutuya label, tıklanan şeye button. İkisi de ekstra kod istemez, sadece doğru etiket.

Hızlı kontrolBaşlangıç

Bir input'un yanında <span>Tutar</span> yazıyor. Ekran okuyucu input'a gelince ne der?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Gönder düğmesi <div onClick=…> ile yazılmış. Klavye kullanıcısı için sonuç?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Renk tek başına konuşmaz

Hatalı tutarı yalnızca kırmızı çerçeveyle göstermek, görmeyen biri için hiçbir şey göstermemektir. Renk körlüğü olan biri için de çoğu zaman öyledir.

Hata metnini yaz ve ARIAHTML'e rol, ad ve durum bilgisi ekleyen öznitelikler (aria-label, aria-invalid). Davranış eklemez; aynı işi yapan HTML öğesi varsa o tercih edilir.Sözlükte gör → ile kutuya bağla: aria-invalid="true" kutunun hatalı olduğunu, aria-describedby hatanın ne olduğunu söyler. Bu sitenin simülatörleri de her durumu renkle birlikte bir simge ve bir yazıyla gösterir.

Kafam karıştı, daha basit anlat

Renk bir ipucu, mesaj değil. Hatayı yaz ve kutuya bağla.

Hızlı kontrolOrta

Tutar hatası yalnızca kırmızı bir çerçeveyle gösteriliyor. En iyi düzeltme hangisi?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Kendin gör

Gözü kapalı para gönder

Tohum 26018

Oynat ya da adımla: her adım bir Tab basışı.

Hız
Adım 0

Şu an ne oldu?

Tab tuşu ve ekran okuyucu

Fare yok, ekran yok. Kullanıcı yalnızca Tab ile ilerliyor ve duyduğuyla karar veriyor.

Görevler0/3

  • Gönder düğmesine klavyeyle hiç ulaşılamasınaçık

    İpucu

    Varsayılan ayarlar yeter.

  • Her şeye ulaşılsın ama tutar hatası sessiz kalsınaçık

    İpucu

    Düğmeyi düzelt, hatayı bırak.

  • Formu gözü kapalı, sorunsuz doldurtaçık

    İpucu

    Dört düzeltmenin hepsi.

Olay günlüğü (0)

Henüz olay yok. Oynat veya adımla.

  1. Varsayılanla oynat. Kutular adsız, hata sessiz, Gönder’e ulaşılamadı.
  2. “button kullan”ı aç. Tab artık Gönder’de duruyor.
  3. Etiketleri aç. Kutular adlarıyla okunuyor.
  4. Hatayı yazıyla bağla. “Geçersiz, bakiye yetersiz” duyuldu.
  5. İkona ad ver. “Düğme” yerine “Kapat, düğme”.
Hızlı kontrolOrta

Yalnızca bir ✕ ikonu olan kapat düğmesi var, yazısı yok. Ekran okuyucu ne der ve nasıl düzeltilir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Tuzaklar

ARIA’yı her yere serpmek. ARIA’nın ilk kuralı: aynı işi yapan bir HTML öğesi varsa onu kullan. div role="button" yazmak, klavye davranışını sana bırakır; button hepsini hazır verir.

Odak çerçevesini silmek. outline: none yazıp yerine bir şey koymamak, klavye kullananın nerede olduğunu görmesini engeller. Çerçeveyi sevmiyorsan :focus-visible ile güzelleştir.

Placeholder’ı etiket sanmak. Yazmaya başlayınca kaybolur, rengi de genellikle soluktur. Kutunun adı görünür bir label’da olsun.

Kafam karıştı, daha basit anlat

Önce doğru HTML, ARIA sadece eksik kalanlar için. Odak çerçevesini silme, placeholder’a güvenme.

Hızlı kontrolOrta

Tasarımcı odak çerçevesini çirkin bulduğu için outline: none yazıldı. Sorun ne?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aşağıdaki örnek bir bankacılık uygulamasının para gönderme formundan: her kontrolün adı var, hata duyuluyor, her şey klavyeyle çalışıyor.

Derinleş · Para gönderme formu: gözü kapalı da doldurulabilir 4 dosya · ~65 satır · ilk okumada atlayabilirsin
Proje dosyaları

src/features/transfer/ TransferForm.tsx Form: her kutunun label'ı var; hata metni kutuya bağlı ve duyuluyor.

src/features/transfer/TransferForm.tsx
interface TransferFormProps {
balance: number;
onSend: (iban: string, amount: number) => void;
}
export function TransferForm({ balance, onSend }: TransferFormProps) {
const [iban, setIban] = useState('');
const [amount, setAmount] = useState('');
const tooMuch = Number(amount) > balance;
return (
<form
onSubmit={(event) => {
event.preventDefault();
if (!tooMuch) onSend(iban, Number(amount));
}}
>
<label htmlFor="iban">Alıcı IBAN</label>
<input id="iban" value={iban} onChange={(e) => setIban(e.target.value)} autoComplete="off" />
<label htmlFor="amount">Tutar</label>
<input
id="amount"
inputMode="decimal"
value={amount}
onChange={(e) => setAmount(e.target.value)}
aria-invalid={tooMuch}
aria-describedby={tooMuch ? 'amount-error' : undefined}
/>
{tooMuch && (
<p id="amount-error" className="error">
✕ Bakiye yetersiz
</p>
)}
<button type="submit">Gönder</button>
</form>
);
}

src/features/transfer/ CloseButton.tsx Kapat düğmesi yalnızca bir ikon; adı aria-label ile veriliyor.

src/features/transfer/CloseButton.tsx
interface CloseButtonProps {
onClose: () => void;
}
export function CloseButton({ onClose }: CloseButtonProps) {
return (
<button type="button" onClick={onClose} aria-label="Kapat">
<svg aria-hidden="true" viewBox="0 0 24 24" width="20" height="20">
<path d="M6 6l12 12M18 6L6 18" stroke="currentColor" strokeWidth="2" />
</svg>
</button>
);
}

src/styles/ focus.css Odak çerçevesi silinmiyor, yalnızca klavye kullanırken güzelleştiriliyor.

src/styles/focus.css
/* Never remove the focus ring; make it fit the design instead. */
:focus-visible {
outline: 2px solid #daa520;
outline-offset: 2px;
}

src/features/transfer/ TransferForm.test.tsx Test: düğmeyi rolü ve adıyla bulmak, ekran okuyucunun gördüğünü test etmektir.

src/features/transfer/TransferForm.test.tsx
it('announces the error and lets the keyboard reach Send', async () => {
render(<TransferForm balance={100} onSend={vi.fn()} />);
await userEvent.type(screen.getByLabelText('Tutar'), '250');
expect(screen.getByLabelText('Tutar')).toHaveAccessibleDescription('✕ Bakiye yetersiz');
expect(screen.getByRole('button', { name: 'Gönder' })).toBeInTheDocument();
});

Kendini sına

Şimşek turu1/4

Ekran okuyucu, ekranda gördüğün renkleri ve çerçeveleri sesli anlatır.

Soru 1/3Orta

Bir ekip her tıklanabilir div'e role="button" ekledi. Bu neden yeterli değil?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aklında kalacak üç şey

  1. 1 Ekran okuyucu ekranı değil, HTML'i okur. Bir kontrolün duyulan adı, ona bağlı label'dan, düğmenin yazısından ya da aria-label'dan gelir.
  2. 2 Tıklanan her şey bir button ya da a olmalı. div onClick fareyle çalışır ama Tab orada durmaz; klavye kullanan biri o işi hiç yapamaz.
  3. 3 Renk tek başına bilgi taşımaz. Hata, yazıyla söylenir ve aria-describedby ile kutuya bağlanır; kutu aria-invalid ile işaretlenir.
Sonraki kapı Kullanıcı Gönder'e bir kez bastı. Ekstresinde aynı havale iki kez görünüyor. Nasıl? Form Gönderimi — Bir Tıkla İki Havale Nasıl Olur? · 8 dk

4 kart sonraki derste seni bekliyor

0/4 kart bu dersten toplandı

Bu dersin üstüne kurulanlar

Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.