WCAG 2.1.1 · A Seviyesi
Klavye Erişimi
Sayfadaki veya uygulamadaki tüm işlevlerin fare ya da dokunma gerektirmeden, klavye veya platforma uygun eşdeğer giriş yöntemleriyle de kullanılabilmesini ister.
Kısaca
Birçok kullanıcı fare veya dokunmatik ekran kullanmaz; sayfayı klavyeyle, anahtar (switch) cihazıyla, ses komutuyla ya da ekran okuyucunun gezinme hareketleriyle kullanır. Bu araçların hepsi, arka planda klavye benzeri bir arayüze dayanır.
Bu kriter, işlevin kendisi bir yol çizmeyi gerektirmedikçe (örneğin serbest çizim) her işlemin klavyeyle de yapılabilmesini ister. Fareyle açılan her menü, tıklanan her düğme ve sürüklenen her öğe için klavyeyle çalışan bir yol bulunmalıdır.
Neleri kapsar?
- Medya oynatıcılar: Oynat, duraklat, ses düzeyi, ileri-geri sarma ve kapatma denetimleri.
- Açılır menüler: Menünün açılması, seçenekler arasında gezinme ve seçim yapma.
- Diyalog kutuları ve açılır pencereler: İçinde gezinme, işlemleri çalıştırma ve kapatma.
- Etkileşimle değişen bileşenler: Üzerine gelince veya tıklayınca açılan alt menüler, ipuçları ve ek içerikler.
- Sürükle-bırak: Sürükleyerek yapılan sıralama, taşıma ve dosya yükleme işlemleri için klavye alternatifi.
- Kapsam dışı notlar: Odağın bir bileşende sıkışıp kalması bir sonraki kriterin (Klavye Kilitlenmesinin Olmaması), odağın gezdiği sıra ise Odaklama Sırası kriterinin konusudur.
Kimleri etkiler?
Kör kullanıcılar ekranı göremedikleri için fare kullanmaz, tamamen klavye ve ekran okuyucu ile çalışır. El titremesi, felç, kas hastalıkları veya uzuv kaybı gibi motor engelleri olan kişiler klavye, anahtar cihazları, ağızla kullanılan çubuklar ya da ses komutu kullanır. Bu yardımcı teknolojilerin tümü, işlevlere klavye üzerinden erişilebilmesine bağlıdır. Hızlı çalışmak için klavyeyi tercih eden kullanıcılar da bu kriterden yararlanır.
Kontrol listesinde
Bu kriter, Bakanlığın A Seviyesi Kontrol Listesi'nde 56–68 numaralı soruları kapsar. Yönlendirme soruları sayfada ilgili içerik olup olmadığını belirler; yoksa liste sizi sonraki soruya geçirir. Aşağıdaki açıklamalar sorulardan alıntı değil, özetidir. Soruların tam metni için resmî listeye bakın.
| Soru | Türü | Ne kontrol eder? |
|---|---|---|
| 56 | Yönlendirme | Klavyeyle veya eşdeğer giriş yöntemleriyle kullanılması gereken etkileşimli bileşen olup olmadığını sorar. |
| 57 | Yönlendirme | Sayfada video, ses veya benzeri bir medya oynatıcı olup olmadığını sorar. |
| 58 | ★ Zorunlu | Oynatıcının tüm denetimlerinin klavyeyle veya eşdeğer yöntemlerle kullanılıp kapatılabildiğini kontrol eder. |
| 59 | Yönlendirme | Sayfada açılır menü olup olmadığını sorar. |
| 60 | ★ Zorunlu | Açılır menünün klavyeyle açılabildiğini, seçenekler arasında gezinilip seçim yapılabildiğini kontrol eder. |
| 61 | Yönlendirme | Sayfada diyalog kutusu olup olmadığını sorar. |
| 62 | ★ Zorunlu | Diyalog kutusunun klavyeyle kullanılabildiğini ve kapatılabildiğini kontrol eder. |
| 63 | Yönlendirme | Kendiliğinden açılan pencere (pop-up) olup olmadığını sorar. |
| 64 | ★ Zorunlu | Kendiliğinden açılan pencerenin odak alabildiğini, içinde gezinilebildiğini ve klavyeyle kapatılabildiğini kontrol eder. |
| 65 | Yönlendirme | Üzerine gelme, odaklanma, dokunma veya tıklama ile durumu değişen ya da ek içerik gösteren bileşen olup olmadığını sorar. |
| 66 | ★ Zorunlu | Bu bileşenlerin ve ortaya çıkan içeriğin klavyeyle de odaklanılabilir ve kullanılabilir olduğunu kontrol eder. |
| 67 | Yönlendirme | Sayfada sürükle-bırak işlevi olup olmadığını sorar. |
| 68 | ★ Zorunlu | Sürükle-bırak ile yapılan işlemin klavyeyle veya eşdeğer bir yöntemle de yapılabildiğini kontrol eder. |
Resmî kontrol listesini indirin (PDF), yeni sekmede açılır
Web için kod örnekleri
1. Tıklanabilir div yerine gerçek düğme
div veya span klavyeyle odak almaz ve Enter/Space ile çalışmaz. Yerleşik button bunların hepsini kendiliğinden sağlar.
<div class="oynat" onclick="videoyuOynat()">
<img src="/ikon/oynat.svg" alt="">
</div><button type="button" class="oynat"
onclick="videoyuOynat()" aria-label="Oynat">
<img src="/ikon/oynat.svg" alt="">
</button>2. Medya oynatıcı denetimleri
Yerleşik controls özniteliği klavyeyle çalışan denetimler sunar. Özel bir oynatıcı yazıyorsanız her denetim bir button veya input type="range" olmalıdır.
<div class="oynatici">
<video id="video" src="/video/vergi-rehberi.mp4"></video>
<button type="button" id="oynat-dugme">Oynat</button>
<label for="ses">Ses düzeyi</label>
<input type="range" id="ses" min="0" max="1" step="0.1" value="1">
<button type="button" id="geri-sar">10 saniye geri sar</button>
</div>
<script>
const video = document.getElementById("video");
const oynat = document.getElementById("oynat-dugme");
oynat.addEventListener("click", () => {
video.paused ? video.play() : video.pause();
oynat.textContent = video.paused ? "Oynat" : "Duraklat";
});
document.getElementById("ses").addEventListener("input",
(e) => { video.volume = Number(e.target.value); });
document.getElementById("geri-sar").addEventListener("click",
() => { video.currentTime = Math.max(0, video.currentTime - 10); });
</script>3. Açılır menü
Menüyü açan düğme aria-expanded ile durumunu bildirmeli; Escape menüyü kapatıp odağı düğmeye döndürmelidir. Gezinme bağlantılarından oluşan menülerde Tab ile ilerlemek yeterlidir.
<li class="menu" onmouseover="ac()" onmouseout="kapat()">
Hizmetler
<ul class="alt-menu">…</ul>
</li><li class="menu">
<button type="button" aria-expanded="false"
aria-controls="hizmetler-menu">Hizmetler</button>
<ul id="hizmetler-menu" hidden>
<li><a href="/hizmetler/imar">İmar işlemleri</a></li>
<li><a href="/hizmetler/ruhsat">Ruhsat başvurusu</a></li>
</ul>
</li>
<script>
const dugme = document.querySelector('[aria-controls="hizmetler-menu"]');
const menu = document.getElementById("hizmetler-menu");
function ayarla(acik) {
dugme.setAttribute("aria-expanded", String(acik));
menu.hidden = !acik;
}
dugme.addEventListener("click", () =>
ayarla(dugme.getAttribute("aria-expanded") !== "true"));
menu.parentElement.addEventListener("keydown", (e) => {
if (e.key === "Escape") { ayarla(false); dugme.focus(); }
});
</script>4. Diyalog kutusu
Yerleşik dialog öğesi showModal() ile açıldığında odağı içine alır, arka planı etkisiz hâle getirir ve Escape ile kapanır.
<button type="button" id="sil-ac">Başvuruyu sil</button>
<dialog id="sil-diyalog" aria-labelledby="sil-baslik">
<h2 id="sil-baslik">Başvuru silinsin mi?</h2>
<p>Bu işlem geri alınamaz.</p>
<form method="dialog">
<button value="iptal">Vazgeç</button>
<button value="sil">Sil</button>
</form>
</dialog>
<script>
const diyalog = document.getElementById("sil-diyalog");
document.getElementById("sil-ac")
.addEventListener("click", () => diyalog.showModal());
diyalog.addEventListener("close", () => {
if (diyalog.returnValue === "sil") { /* silme işlemi */ }
document.getElementById("sil-ac").focus();
});
</script>5. Üzerine gelince görünen ipucu
Yalnızca :hover ile görünen içerik klavye kullanıcısına hiç ulaşmaz. :focus-within veya :focus-visible ekleyin.
.ipucu-kapsayici:hover .ipucu {
display: block;
}.ipucu-kapsayici:hover .ipucu,
.ipucu-kapsayici:focus-within .ipucu {
display: block;
}6. Sürükle-bırak için klavye alternatifi
Sıralanabilir listelerde her öğeye "yukarı taşı" ve "aşağı taşı" düğmeleri eklemek basit ve güvenilir bir alternatiftir. Değişikliği ekran okuyucuya bir durum bölgesiyle bildirin.
<ol id="belgeler">
<li>
<span>Nüfus kayıt örneği</span>
<button type="button" class="yukari">Yukarı taşı<span class="sr-only">: Nüfus kayıt örneği</span></button>
<button type="button" class="asagi">Aşağı taşı<span class="sr-only">: Nüfus kayıt örneği</span></button>
</li>
…
</ol>
<p id="siralama-durumu" role="status" class="sr-only"></p>
<script>
const liste = document.getElementById("belgeler");
const durum = document.getElementById("siralama-durumu");
liste.addEventListener("click", (e) => {
const oge = e.target.closest("li");
if (!oge) return;
const yukari = e.target.closest(".yukari");
const asagi = e.target.closest(".asagi");
if (yukari && oge.previousElementSibling) {
liste.insertBefore(oge, oge.previousElementSibling);
yukari.focus();
} else if (asagi && oge.nextElementSibling) {
liste.insertBefore(oge.nextElementSibling, oge);
asagi.focus();
} else return;
const sira = [...liste.children].indexOf(oge) + 1;
durum.textContent = `${oge.querySelector("span").textContent}, ${sira}. sıraya taşındı.`;
});
</script>Mobil için kod örnekleri
Mobilde "klavye erişimi", harici klavye, anahtar erişimi (Switch Control / Switch Access) ve ekran okuyucu hareketleri ile kullanım anlamına gelir. Standart bileşenler bunları kendiliğinden destekler; sürükleme gibi hareketlere ise erişilebilirlik eylemi eklenmelidir.
iOS (SwiftUI)
import SwiftUI
struct BelgeSiralama: View {
@State private var belgeler = ["Nüfus kayıt örneği", "İkametgâh", "Gelir belgesi"]
var body: some View {
List {
ForEach(belgeler, id: \.self) { belge in
Text(belge)
// VoiceOver'da yukarı/aşağı kaydırarak seçilen özel eylemler
.accessibilityAction(named: "Yukarı taşı") { tasi(belge, -1) }
.accessibilityAction(named: "Aşağı taşı") { tasi(belge, 1) }
}
.onMove { belgeler.move(fromOffsets: $0, toOffset: $1) }
}
}
private func tasi(_ belge: String, _ yon: Int) {
guard let i = belgeler.firstIndex(of: belge) else { return }
let hedef = i + yon
guard belgeler.indices.contains(hedef) else { return }
belgeler.swapAt(i, hedef)
}
}Android (Jetpack Compose)
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.*
@Composable
fun BelgeSiralama() {
val belgeler = remember {
mutableStateListOf("Nüfus kayıt örneği", "İkametgâh", "Gelir belgesi")
}
Column {
belgeler.forEachIndexed { i, belge ->
Text(
belge,
modifier = Modifier
.fillMaxWidth()
.clickable(onClickLabel = "Belgeyi aç") { /* aç */ }
.semantics {
customActions = listOf(
CustomAccessibilityAction("Yukarı taşı") {
if (i > 0) { belgeler.add(i - 1, belgeler.removeAt(i)); true } else false
},
CustomAccessibilityAction("Aşağı taşı") {
if (i < belgeler.lastIndex) { belgeler.add(i + 1, belgeler.removeAt(i)); true } else false
}
)
}
)
}
}
}Nasıl test edilir?
- Fareyi bir kenara bırakın: Sayfayı yalnızca Tab, Shift+Tab, Enter, Space, yön tuşları ve Escape ile kullanın. Fareyle yapılabilen her işlemi klavyeyle de yapabiliyor musunuz?
- Odak göstergesini izleyin: Odak her an görünüyor mu? Odaklanılan öğe çalıştırılabiliyor mu? (Odağın görünürlüğü AA düzeyinde ayrı bir kriterdir, ancak test sırasında sorunları fark etmenizi kolaylaştırır.)
- Bileşenleri tek tek deneyin: Menüleri açıp kapatın, diyalogları kapatın, medya oynatıcıyı kullanın, ipuçlarını görüntüleyin, sıralama işlemini klavyeyle yapın.
- Mobilde harici klavye ve anahtar erişimi: Tablete Bluetooth klavye bağlayın veya Switch Control / Switch Access'i açın; tüm işlemleri bu yolla deneyin.
- Otomatik araçların sınırı: Otomatik araçlar
onclicktaşıyan ama odak alamayan öğeleri, pozitiftabindexdeğerlerini ve rolü olmayan etkileşimli öğeleri bulabilir. Ancak bir işlevin klavyeyle gerçekten tamamlanıp tamamlanamadığını ölçemez; bu kriter mutlaka elle test edilmelidir.
Sık yapılan hatalar
- Tıklanabilir div ve span: Tasarım kolaylığı için düğme yerine kullanılır ve klavyeyle çalışmaz.
- Yalnızca fare olaylarına bağlanmak:
mouseover,mousedownveyadblclickile tetiklenen işlevlerin klavye karşılığı yoktur. - Odak çerçevesini kaldırmak:
outline: nonekullanıp yerine başka bir gösterge koymamak, klavye kullanıcısının nerede olduğunu bilmesini engeller. - Bağlantıyı düğme gibi kullanmak:
hrefiçermeyenaöğeleri odak almaz. - Sürükle-bırak dosya yükleme alanları: Yanında "Dosya seç" düğmesi olmayan yükleme alanları klavyeyle kullanılamaz.
- Özel bileşen kütüphanelerine güvenmek: Hazır bileşenlerin klavye desteği her zaman eksiksiz değildir; kullanmadan önce test edin.
Kaynaklar
- Understanding SC 2.1.1: Keyboard (W3C), İngilizce, yeni sekmede açılır
- Erişilebilirlik blogu — Uygulamadan örnekler ve güncel yazılar.
- Erişilebilirlik kütüphanesi — Klavye erişimi, odak, çalıştırılabilir ve diğer terimler.
Sitenizde bu kriter nasıl görünüyor?
Ücretsiz tarama, bu kriterdeki sorunları ve diğerlerini Bakanlığın A Seviyesi Kontrol Listesi esas alınarak listeler.
Sıradaki kriterler
Klavye Kilitlenmesinin Olmaması
Klavyeyle veya eşdeğer bir yöntemle ulaşılan bir bileşenden yine aynı yöntemle çıkılabilmesini, odağın hiçbir yerde sıkışıp kalmamasını ister.
Kriteri inceleKlavye Kısayolları
Tek bir harf, rakam veya sembolle çalışan kısayolların kapatılabilmesini, değiştirilebilmesini ya da yalnızca ilgili bileşen odaktayken etkin olmasını ister.
Kriteri inceleMetinsel Olmayan İçerik
Görseller, ikonlar, grafikler ve diğer metinsel olmayan içerikler, onları göremeyen kullanıcılara bir metin alternatifiyle aktarılmalıdır.
Kriteri incele