Web erişilebilirliği: kontrast, klavye, alt metin ve nasıl test edilir
Erişilebilirlik çoğu projede en sona bırakılan konu oluyor, oysa temel kısmı bir sitenin geri kalanını yazarken neredeyse ek maliyetsiz yapılabiliyor. Doğru HTML öğesini seçmek, rengi bir kez kontrol etmek, görsele bir cümle açıklama yazmak. Bunlar yapılmadığında ise ekran okuyucu kullanan, klavyeyle gezinen, gözü yorgun ya da güneş altında telefona bakan herkes siteden eksik bilgiyle çıkıyor.
Bu yazıda en sık karşılaşılan konuları ve bunları nasıl test ettiğimi anlatıyorum. Örneklerin bir kısmı portföyümdeki kurumsal site hız çalışmasından; orada Lighthouse erişilebilirlik puanı 89'dan 100'e çıktı. Yazının sonunda bu puanın neyi söyleyip neyi söylemediğine de değineceğim.
Renk kontrastı
WCAG 2.2'nin AA seviyesi normal metin için en az 4,5:1, büyük metin için (yaklaşık 24 px ve üstü ya da 18,66 px ve üstü kalın) en az 3:1 kontrast istiyor. Düğme kenarları, form alanı çerçeveleri ve ikonlar gibi arayüz öğeleri için de sınır 3:1.
Lojistik firması sitesinde sorun marka turuncusuydu. Açık turuncu (#f0a020) beyaz zemin üzerinde yaklaşık 2,15:1 veriyor; başlıkta bile yetmiyor. Rengi bırakmadım, rolünü değiştirdim:
| Kullanım | Renkler | Oran |
|---|---|---|
| Beyaz zeminde turuncu metin (eski) | #f0a020 / #fff | 2,15:1 |
| Beyaz zeminde turuncu metin (yeni, koyulaştırılmış) | #9a5a00 / #fff | 5,47:1 |
| Turuncu düğme üstünde koyu metin | #111 / #f0a020 | 8,77:1 |
Açık turuncu zemin rengi olarak kaldı, metin olarak kullanılan yerlerde koyu tonu geçti. Marka kimliği bozulmadan AA sınırının üstüne çıktı.
Kontrastı tek tek kontrol etmek yerine otomatiğe bağlamak daha güvenli. Portföyümdeki mobil bankacılık uygulaması çalışmasında 16 metin/zemin çiftinin minimum oranlarını hem açık hem koyu temada birim testleriyle doğruluyorum; birisi paletteki bir rengi değiştirip sınırın altına düşürürse testler kırılıyor.
Klavye ile gezinme ve odak
Fareyi bırakın, sadece Tab, Shift+Tab, Enter, Boşluk ve ok tuşlarıyla sitenizi gezin. Şu soruları sorun:
- Her bağlantıya, düğmeye ve form alanına ulaşabiliyor musunuz?
- Odak nerede, görebiliyor musunuz?
- Sıra mantıklı mı, yoksa sayfanın bir ucundan diğerine mi atlıyor?
- Açılan menü ya da pencereden Esc ile çıkabiliyor musunuz, odak geri dönüyor mu?
En sık görülen iki hata: CSS'te outline: none yazıp yerine hiçbir şey koymamak ve tıklanabilir öğeyi <div onclick> ile yapmak. <div>'e klavyeyle ulaşılamaz, Enter'a tepki vermez, ekran okuyucu onu düğme olarak duyurmaz. Düğme işi yapan şeyi <button>, sayfa değiştireni <a href> yapın; klavye desteği bedavaya gelir.
Uzun menüsü olan sitelerde bir de "içeriğe geç" bağlantısı eklemek işe yarıyor. Klavye kullanıcısı her sayfada menüdeki yirmi bağlantıyı tek tek geçmek zorunda kalmıyor:
<a class="skip" href="#icerik">İçeriğe geç</a>
...
<main id="icerik">...</main>
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 12px; top: 12px; background: #fff; padding: 8px 12px; z-index: 10; }
:focus-visible { outline: 3px solid #7cb7e0; outline-offset: 2px; }
İçeriğe geç bağlantısı lojistik firması sitesindekiyle aynı; orada form alanlarına da 3 px'lik belirgin bir odak halkası ekledim. Genel odak stili için :focus-visible kullanmanızı öneririm: düğme ve bağlantılarda odak halkası fareyle tıklayınca değil, klavyeyle gezerken görünüyor; tasarımcıların odak halkasını kaldırma isteğine karşı iyi bir orta yol.
Sayfanın yapısı: alt metin ve başlıklar
Alt metin
Alt metin görseli göremeyen kişiye görselin o sayfadaki işlevini anlatır. Üç durum var:
- İçerik taşıyan görsel: ne gösterdiğini kısaca yazın. "Limanda istiflenmiş renkli konteynerler ve vinçler" gibi. "görsel", "resim1.jpg" ya da anahtar kelime yığını değil.
- Bağlantı ya da düğme olan görsel: nereye gittiğini ya da ne yaptığını yazın. Bir logo bağlantısı için "Ana sayfa" yeterli.
- Süs görseli:
alt=""verin. Boş alt metin ekran okuyucuya "bunu atla" der;altözniteliğini hiç yazmamak ise bazı ekran okuyucuların dosya adını okumasına yol açar.
Lojistik firması sitesinin eski sürümünde tersi bir hata vardı: dört içerik görselinin dördünde de alt="" yazıyordu, yani ekran okuyucuya hepsi süs olarak bildiriliyordu. Yeni sürümde her görselin kendi açıklaması var.
Başlık sırası
Ekran okuyucu kullanıcılarının çoğu sayfayı başlıklar arasında atlayarak tarar. Bu yüzden başlıklar sayfanın içindekiler tablosu gibi olmalı: bir h1, altında h2'ler, gerekiyorsa onların altında h3'ler. Seviye atlamamak (h2'den h4'e geçmemek) ve başlık etiketini sırf yazı büyük görünsün diye kullanmamak gerekiyor. Görsel boyut CSS'in işi, başlık seviyesi yapının.
Aynı sitenin eski sürümünde bir bölümde h2'den doğrudan h4'e geçiliyordu. Başlıklar yapıya göre yeniden düzenlendi. Tarayıcı eklentileriyle ya da DevTools'taki erişilebilirlik ağacıyla başlık yapısını bir liste halinde görmek, sorunları hemen ortaya çıkarıyor.
Form etiketleri ve hata mesajları
Yer tutucu metin (placeholder) etiket değildir. Yazmaya başlayınca kaybolur, kontrastı genellikle düşüktür ve her ekran okuyucu onu güvenilir şekilde okumaz. Her alanın görünür bir <label>'ı olmalı ve bu etiket alana bağlı olmalı:
<label for="telefon">Telefon</label>
<input id="telefon" name="telefon" type="tel" autocomplete="tel"
aria-describedby="telefon-hata" aria-invalid="true">
<p id="telefon-hata">Telefon numarası 10 haneli olmalı.</p>
for ile id eşleşince etikete tıklamak alanı odaklar, ekran okuyucu da alana gelince etiketi okur. aria-describedby hata mesajını alana bağlar. Hatayı sadece kırmızı çerçeveyle göstermek yetmez; rengi ayırt edemeyen biri için metin olarak da yazmalısınız. autocomplete özniteliği de hem mobilde hem motor becerisi kısıtlı kullanıcılar için ciddi kolaylık.
Nasıl test ediyorum?
Otomatik araçlar hızlı ama eksik; bu yüzden üç katmanlı bir test işe yarıyor.
Lighthouse. Chrome DevTools'ta erişilebilirlik kategorisi. Arka planda axe-core kurallarının bir alt kümesini çalıştırıyor. Kontrast, eksik alt, etiketsiz form alanı, lang eksikliği gibi makinenin görebileceği hataları yakalıyor.
axe. Tarayıcı eklentisi olarak ya da testlerin içinde. Playwright kullanıyorsanız @axe-core/playwright paketiyle her sayfayı uçtan uca testlerde tarayabilir, yeni bir hata eklendiğinde testi kırabilirsiniz:
import AxeBuilder from '@axe-core/playwright';
test('ana sayfada erişilebilirlik ihlali yok', async ({ page }) => {
await page.goto('/');
const sonuc = await new AxeBuilder({ page }).analyze();
expect(sonuc.violations).toEqual([]);
});
Elle test. Klavyeyle bir tur, ardından ekran okuyucuyla bir tur. Windows'ta NVDA ücretsiz, macOS ve iOS'ta VoiceOver, Android'de TalkBack hazır geliyor. Ekran okuyucuyla ilk kez kendi sitenizi dinlediğinizde, alt metnin ya da başlık yapısının neden önemli olduğu çok netleşiyor.
Lighthouse'ta 100 almak "site erişilebilir" demek değil. Otomatik araçlar bir alt metnin var olup olmadığını görür ama doğru olup olmadığını bilemez; odak sırasının mantıklı olup olmadığını, bir açılır menünün Esc ile kapanıp kapanmadığını da anlayamaz. Lojistik firması sitesindeki 100 puan, bilinen sorunların giderildiği anlamına geliyor; elle test hâlâ gerekli.
Kısa kontrol listesi
- Metin kontrastı en az 4,5:1, büyük metin ve arayüz öğeleri en az 3:1.
- Bütün işlevler klavyeyle kullanılabiliyor, odak her zaman görünür.
- Tıklanabilir her şey
<button>ya da<a>. - İçerik görsellerinde anlamlı
alt, süs görsellerindealt="". <html lang="tr">tanımlı, tekh1var ve başlıklar seviye atlamıyor.- Her form alanının bağlı bir
<label>'ı var, hatalar metin olarak yazılıyor. - Lighthouse ve axe temiz; klavye ve ekran okuyucuyla en az bir tur yapıldı.
Sitenizi bu listeye göre gözden geçirmek isterseniz bana yazabilirsiniz.