Erişilebilirlik çoğu zaman projenin sonuna eklenen bir kontrol listesi gibi ele alınır. Tasarım bitince bir bakılır, kontrast biraz artırılır, birkaç alt metni yazılır ve iş kapanır. Oysa temel HTML doğru kullanıldığında işin büyük kısmı kendiliğinden çözülür. Asıl risk, yanlış bir yapıyı sonradan düzeltmeye çalışmaktır.

Bir arayüz klavyeyle gezilemiyorsa, bazı kullanıcılar için hiç var olmamış demektir. Bu cümle biraz sert gelebilir, ama işin gerçeği bu. Bu metinde, erişilebilirliği bir özellik olarak değil, tasarımın ve geliştirmenin temeli olarak nasıl düşünebileceğimizi anlatacağım.

Semantik ilk adımdır

Bir düğme ya da bağlantı için doğru HTML öğesini seçmek, klavye desteğinin ve ekran okuyucu duyurusunun büyük kısmını bedavaya getirir. button öğesi Enter ve Space ile tetiklenir, odaklanabilir ve okuyucu tarafından "düğme" olarak duyurulur. Aynı işi yapan bir div, bu üç özelliğin üçünü de kaybeder.

<!-- Yanlış: görsel bir düğme, ama bir düğme değil -->
<div class="cursor-pointer" onclick="kaydet()">Kaydet</div>

<!-- Doğru: tarayıcı ve yardımcı teknoloji bunu tanır -->
<button type="button" onclick="kaydet()">Kaydet</button>

Bu kural başlıklar için de geçerli. Bir sayfada yalnızca bir h1 olması, başlık düzeylerinin atlanmadan ilerlemesi ve bölümlerin section, nav, main gibi işaretçilerle ayrılması, ekran okuyucu kullanıcılarının sayfayı hızla taramasını sağlar.

Erişilebilir arayüz, herkes için daha sakin bir arayüzdür.

Klavye: her şey Tab ile ulaşılabilir olmalı

Klavye ile gezinme, yalnızca görme engelli kullanıcılar için değil, fare kullanamayan, elini kullanamayan ya da yalnızca klavye kısayollarını seven herkes için önemlidir. Temel kural basittir: sayfadaki her etkileşimli öğe Tab ile odaklanabilmeli ve Enter ya da Space ile etkinleşmelidir.

Odak göstergesi de bu kuralın parçasıdır. Tarayıcının varsayılan odak halkasını kaldırmak, klavye kullanıcılarını nerede olduklarını bilmeden bırakır. Görsel olarak daha temiz bir tasarım istiyorsanız, varsayılanı kaldırmak yerine kendi odak stilinizi tanımlayın.

a:focus-visible,
button:focus-visible,
input:focus-visible {
    outline: 2px solid var(--color-brand-600);
    outline-offset: 2px;
}
  • :focus-visible yalnızca klavye ile odaklanıldığında görünür; fare tıklamasında gereksiz bir çerçeve çıkmaz.
  • Sayfanın ilk öğesi olarak "İçeriğe atla" bağlantısı ekleyin; klavye kullanıcıları menüyü her sayfada baştan geçmek zorunda kalmasın.
  • Tab sırası, görsel düzenle aynı olmalıdır. CSS ile yer değiştiren öğeler, odak sırasını karıştırabilir.

Renk kontrastı ve metin

Normal boyuttaki metin için WCAG AA düzeyinde en az 4,5:1 kontrast oranı beklenir; büyük metinler için bu eşik 3:1'dir. Bu rakamlar bir tasarım tercihi değil, ölçülebilir bir alt sınırdır. Açık gri bir metnin beyaz üzerinde zarif görünmesi, düşük görüşlü biri için okunamaz olabilir.

Kontrastı yalnızca metin rengiyle değil, sınır ve durum renkleriyle de düşünmek gerekir. Bir girdinin kenarlığı arka plandan çok az ayrılıyorsa, girdinin orada olduğu anlaşılmayabilir. Hata durumunu yalnızca kırmızıyla göstermek de renk körü kullanıcılar için yeterli değildir; bir simge ya da metin de eklenmelidir.

ÖğeAsgari kontrastNot
Normal metin4,5:1Gövde metni, bağlantılar
Büyük metin3:1Yaklaşık 24 piksel ve üzeri, ya da kalın 18,66 piksel
Arayüz bileşeni3:1Girdi kenarlığı, odak halkası, simge

Form: etiket, hata ve yardım

Formlar, erişilebilirliğin en çok ihmal edilen alanıdır. Bir girdinin etiketi olmadığında, ekran okuyucu kullanıcısı alanın ne istediğini bilemez. Yer tutucu metin (placeholder) etiketin yerini tutamaz; yazı yazılmaya başlandığında kaybolur ve bir çok kişi için yeterince görünür değildir.

<label for="eposta">E-posta adresiniz</label>
<input id="eposta" name="eposta" type="email" autocomplete="email"
       aria-describedby="eposta-ipucu eposta-hata" aria-invalid="true">
<p id="eposta-ipucu">Bültenimizi bu adrese göndereceğiz.</p>
<p id="eposta-hata">Lütfen geçerli bir e-posta adresi girin.</p>

Bu örnekte aria-describedby hem ipucunu hem de hata mesajını girdiye bağlar. Kullanıcı girdiye odaklandığında, bu metinler ekran okuyucu tarafından okunur. aria-invalid ise hatanın varlığını bildirir.

  • Her girdinin görünür bir etiketi olsun; yalnızca yer tutucu yetmez.
  • Hata mesajı, hatanın olduğu alanın yanında ve metin olarak yazılsın.
  • Zorunlu alanlar hem görsel olarak hem de required ile işaretlensin.

Görseller: alt metni ne zaman yazılır?

Bir görselin alt metni, o görselin sayfada ne anlama geldiğini söyler. Dekoratif bir görselse, boş bir alt="" yeterlidir; ekran okuyucu onu atlar. Anlamlı bir görselse, içeriğini kısaca anlatmalıdır.

Yanlış bir alt metni, bazen hiç olmamasından daha kötüdür. "Resim" ya da dosya adı yazmak, kullanıcıya bir şey anlatmaz. İyi bir alt metni, görselin neden orada olduğunu söyler: "Çalışma masasında bir dizüstü bilgisayar ve bir not defteri" gibi.

Hareket hassasiyeti

prefers-reduced-motion tercihine saygı göstermek, animasyonları tamamen kaldırmak değildir; yoğunluğunu azaltmaktır. Bazı kullanıcılar kayan, zıplayan ya da dönen öğelerle baş dönmesi yaşayabilir. İşletim sisteminde bu tercih açıksa, uzun ve sarsıcı hareketleri kapatmak, kısa geçişleri ise sürdürmek yeterlidir.

@media (prefers-reduced-motion: reduce) {
    .reveal {
        transition: none;
        transform: none;
    }
}

Dinamik içerik ve canlı bölgeler

Sayfa yenilenmeden değişen içerik, ekran okuyucu kullanıcısı için görünmez olabilir. Bir arama sonucu güncellendiğinde, bu değişikliğin duyurulması gerekir. Bunun için aria-live özniteliği kullanılır: polite değeri değişikliği kullanıcıyı kesmeden bildirir, assertive ise yalnızca gerçekten acil durumlarda kullanılmalıdır.

Modal, açılır menü ya da sekme gibi bileşenlerde ise odak yönetimi devreye girer. Bir modal açıldığında odak içeri taşınmalı, kapandığında ise onu açan öğeye dönmelidir. Bunu atlamak, klavye ve ekran okuyucu kullanıcılarını sayfanın başına geri atar.

Test etmek: kendi ellerinizle

Erişilebilirlik kontrol listeleri yararlıdır, ama yetmez. Gerçek bir denetim, sayfayı yalnızca klavye ile baştan sona gezerek ve bir ekran okuyucu açarak yapılır. Bu iki deneme, listenin kaçırdığı sorunları çoğu zaman ortaya çıkarır.

  1. Fareyi bir kenara koyun ve sayfayı yalnızca Tab, Shift+Tab, Enter ve Space ile dolaşın.
  2. Her etkileşimli öğenin odak halkasını görüp görmediğinizi kontrol edin.
  3. Bir ekran okuyucu açıp ana bölümler arasında başlıklarla gezinin.
  4. Bir formu hatalı doldurup hata mesajının duyulup duyulmadığına bakın.
  5. Renklerin yalnızca tonla değil, metin ya da simgeyle de anlatıldığını doğrulayın.
Bir arayüzü erişilebilir yapmanın en hızlı yolu, onu bir kez gözleri kapalı kullanmaya çalışmaktır.

Ekran okuyucu ile gerçek bir denetim

Ekran okuyucu kullanmayı hiç denemediyseniz, bu bölüm sizin için bir başlangıç olabilir. Windows'ta NVDA ücretsizdir; macOS ve iOS'ta VoiceOver işletim sisteminin içinde gelir; Android'de ise TalkBack bulunur. Bu araçları bir kez açıp kapatmak bile, yazdığınız bir sayfanın nasıl duyulduğu hakkında çok şey öğretir.

Ekran okuyucu kullanıcıları sayfayı çoğu zaman baştan sona okumaz; başlıkları, bölümleri ve formları hızla dolaşarak gezinir. NVDA tarayıcı modunda H tuşu başlıklar arasında, D tuşu bölüm işaretçileri arasında, F tuşu ise form alanları arasında geçiş yapar. Bu kısayollar çalışmıyorsa, sayfanın yapısı büyük olasılıkla eksiktir.

  • Başlıklar sırayla ilerliyor mu? h1'den sonra h3 gelmesi, yapıda bir boşluk demektir.
  • Bölümler main, nav, footer gibi işaretçilerle ayrılmış mı?
  • Bağlantı metinleri tek başına anlamlı mı? "Devamını oku" yerine bir yazının adını içeren metin tercih edin.

Tablolar: başlıklar ve kapsam

Veri tabloları, ekran okuyucu için en karmaşık yapılardan biridir. Bir kullanıcı hücreye geldiğinde, o hücrenin hangi sütuna ve satıra ait olduğunu bilmesi gerekir. Bu bilgi, başlık hücrelerinin doğru işaretlenmesiyle sağlanır.

<table>
    <caption>Son yedi günde en çok okunan yazılar</caption>
    <thead>
        <tr>
            <th scope="col">Yazı</th>
            <th scope="col">Görüntüleme</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th scope="row">Kapadokya'da sabah ışığı</th>
            <td>1.240</td>
        </tr>
    </tbody>
</table>

caption öğesi tablonun ne anlattığını söyler, scope özniteliği ise başlığın bir sütuna mı yoksa bir satıra mı ait olduğunu belirtir. Bu iki öznitelik, görsel olarak görünmeyen ama kritik bir bağlamı taşır. Düzen amacıyla tablo kullanmak ise, ekran okuyucu için tamamen yanıltıcıdır; bu durumda düzeni CSS ile kurmak daha doğrudur.

Dil bildirimi ve karışık metinler

Bir sayfanın dili, ekran okuyucunun hangi ses ve telaffuz kurallarıyla okuyacağını belirler. html etiketindeki lang="tr" özniteliği, sayfanın Türkçe olduğunu bildirir. Ama Türkçe bir metnin içinde İngilizce bir terim geçtiğinde, o terimi ayrıca işaretlemek gerekir.

<p>Yazının başlığı <span lang="en">Tailwind CSS</span> ile ilgili.</p>

Bu işaret, yanlış telaffuzu ve anlaşılmaz okumaları önler. Kısa terimler için bile bu adım, uzun bir metinde okuyucunun akışını korur. Kodda kullanılan teknik adlar için de aynı kural geçerlidir.

Yanıp sönme ve dikkat

Ekranda saniyede üçten fazla yanıp sönen içerik, fotosensitif epilepsisi olan kişiler için nöbet riski taşır. WCAG bu sınırı açıkça belirler. Bu nedenle sürekli yanıp sönen ya da hızla titreşen öğeler tasarımdan çıkarılmalıdır.

Dikkat dağınıklığı da benzer bir sorundur. Sürekli hareket eden bir kaydırıcı, otomatik değişen bir pankart ya da arka planda akan bir animasyon, bazı kullanıcılar için metni okumayı imkânsız kılar. Otomatik değişen içerikte bir durdurma düğmesi bulunmalı ve bu düğme klavye ile erişilebilir olmalıdır.

Zaman sınırları ve oturum

Bir formu doldurmak ya da bir sepeti tamamlamak için zaman tanınmalıdır. Süre dolduğunda oturumun kapanması, özellikle yavaş okuyan ya da yardımcı teknoloji kullanan kişiler için bir engeldir. Süre sınırı varsa, dolmadan önce uyarı verilmeli ve süreyi uzatma seçeneği sunulmalıdır.

Bu kural, yalnızca bankacılık ya da ödeme ekranları için değil, her oturum açan site için geçerlidir. Bir yönetim panelinde bile kullanıcının uzun bir metin yazarken kaybolmaması gerekir. Taslağın otomatik kaydedilmesi bu sorunu büyük ölçüde çözer.

Her sürümde kısa bir kontrol

Erişilebilirlik bir kez yapılıp bitirilen bir iş değildir. Her yeni özellik, her yeni bileşen ve her yeni sayfa, mevcut kuralları bozabilir. Bu yüzden ekipte bir inceleme alışkanlığı olmalıdır: değişikliğin klavyeyle gezilebilir olduğunu, başlıkların düzgün olduğunu ve yeni metinlerin kontrastının tutarlı kaldığını kontrol etmek.

Bu kontrol, uzun sürmek zorunda değildir. Beş dakikalık bir klavye turu ve bir başlık listesi, çoğu sorunu yakalamak için yeterlidir. Büyük değişikliklerde ise bir ekran okuyucu oturumu planlanabilir.

Sonuç

Erişilebilirlik, bir son dakika düzeltmesi değildir. Doğru HTML öğesini seçmek, klavye sırasını düşünmek, kontrastı ölçmek ve formu bir bütün olarak ele almak, işin en büyük kısmını oluşturur. Bunlar baştan yapıldığında maliyet düşük, sonuç ise herkes için daha iyidir.

Yeni bir sayfa tasarlarken şu soruları sorun:

  • Her etkileşim doğru HTML öğesiyle mi kuruldu?
  • Klavye ile tamamı gezilebiliyor mu ve odak nerede görünüyor?
  • Metinler ve arayüz bileşenleri yeterli kontrasta sahip mi?
  • Formlar etiketli, hatalar bağlı ve anlaşılır mı?
  • Dinamik değişiklikler duyuruluyor mu?