---
title: 'Odak ve Klavye Etkileşimi'
source: 'https://academia.sh/tr/kurslar/tarayici-platformu/odak-ve-klavye-etkilesimi'
course: 'Tarayıcı ve Web Platformu'
language: tr
updated: '2026-08-17T18:09:12+00:00'
license: 'CC BY-SA 4.0'
---

# Odak ve Klavye Etkileşimi

Girdiyi alan tek ögenin belirlenmesi; odaklanabilirlik koşulları, sekme sırasının hesabı, odak olaylarının kabarma davranışı, tuş olaylarının taşıdığı bilgi ve grup içinde tek durak bırakan gezinme düzeni.

Önceki ders, klavye davranışlarının iptal edilmemesi gereken davranışlar arasında
olduğunu söyledi. Gerekçe şudur: sayfayla etkileşimin tamamı işaretleme aygıtıyla
kurulmaz. Kullanıcı sekme tuşuyla ögeler arasında dolaşır, boşlukla düğmeye basar, ok
tuşlarıyla seçenekler arasında geçer; ekran okuyucu da aynı yolu izler.

Bu dolaşımın merkezinde tek bir kavram vardır: belgede her an en çok bir öge girdiyi
alır. O ögenin adı **etkin öge (active element)** dir ve klavyeden gelen olayların hedefi
odur. Bu ders etkin ögenin nasıl belirlendiğini ve klavye olaylarının hangi bilgiyi
taşıdığını kurar.

## Odaklanabilirlik

**Odak (focus)**, girdiyi alma yetkisidir. Her öge odak alamaz. Bir ögenin odak
alabilmesi üç koşula bağlıdır.

Birincisi **doğal odaklanabilirliktir**. Bağlantılar, düğmeler, form alanları ve
denetimler odak alır; bunun için ek bir bildirim gerekmez. Metin taşıyan bir bölüm ya da
bir listeye odak, ancak açıkça istendiğinde verilir.

İkincisi **görünürlüktür**. Belgeden gizlenmiş bir öge odak alamaz; gizli bir ögeye odak
vermeye çalışan kod sessizce başarısız olur. Bu, açılır bir panelin kapanma anında
odağın kaybolmasının kaynağıdır.

Üçüncüsü **etkinliktir**. Devre dışı bırakılmış bir denetim odak almaz; klavye
kullanıcısı onu hiç görmez. Buradan bir tasarım sonucu çıkar: bir düğmeyi devre dışı
bırakmak, onunla ilgili hata iletisini de erişilemez kılabilir. Nedeni ögenin üzerinde
duramamaktır.

Odak alan ögenin görsel bir işareti olması zorunludur. WCAG 2.4.7 ölçütü, odaklanmış
ögenin görünür bir göstergesi olmasını gerektirir. Odak göstergesini biçemden kaldıran
kod, göreni olmayan bir imleçle çalışmaya benzer bir durum üretir.

## Sekme Sırası

Sekme tuşu odağı belge sırasına göre taşır. Bu sıra, `tabindex` özniteliğiyle
değiştirilebilir ve değerin işareti üç farklı davranış üretir.

```js
// sekme.mjs — sekme sirasinin belge sirasindan ve tabindex degerinden turetilmesi
const ogeler = [
  { ad: "a.atlama-bagi",      tabindex: null, dogalOdaklanir: true,  gizli: false, devreDisi: false },
  { ad: "input#suzgec",       tabindex: null, dogalOdaklanir: true,  gizli: false, devreDisi: false },
  { ad: "button#suz",         tabindex: null, dogalOdaklanir: true,  gizli: false, devreDisi: false },
  { ad: "button#disaAktar",   tabindex: 1,    dogalOdaklanir: true,  gizli: false, devreDisi: false },
  { ad: "div#ozet",           tabindex: -1,   dogalOdaklanir: false, gizli: false, devreDisi: false },
  { ad: "span.rozet",         tabindex: null, dogalOdaklanir: false, gizli: false, devreDisi: false },
  { ad: "button.sil[T-01]",   tabindex: null, dogalOdaklanir: true,  gizli: false, devreDisi: false },
  { ad: "button.sil[T-02]",   tabindex: null, dogalOdaklanir: true,  gizli: false, devreDisi: true  },
  { ad: "button#gonder",      tabindex: null, dogalOdaklanir: true,  gizli: true,  devreDisi: false },
  { ad: "div.satir-kabi",     tabindex: 0,    dogalOdaklanir: false, gizli: false, devreDisi: false },
];

const odaklanabilir = (o) =>
  !o.gizli && !o.devreDisi && (o.dogalOdaklanir || o.tabindex !== null);
const siradaYerAlir = (o) => odaklanabilir(o) && (o.tabindex === null ? true : o.tabindex >= 0);

const sekmeSirasi = (liste) => {
  const belgeSirasi = liste.map((o, i) => ({ ...o, i })).filter(siradaYerAlir);
  const pozitif = belgeSirasi.filter((o) => (o.tabindex ?? 0) > 0)
    .sort((a, b) => a.tabindex - b.tabindex || a.i - b.i);
  const sifir = belgeSirasi.filter((o) => (o.tabindex ?? 0) === 0);
  return [...pozitif, ...sifir];
};

console.log("sekme sirasi:");
for (const [n, o] of sekmeSirasi(ogeler).entries())
  console.log(`  ${n + 1}. ${o.ad.padEnd(18)} tabindex=${o.tabindex ?? "yok"}`);

console.log("sirada olmayanlar:");
for (const o of ogeler.filter((o) => !siradaYerAlir(o))) {
  const neden = o.gizli ? "gizli" : o.devreDisi ? "devre disi"
    : o.tabindex === -1 ? "tabindex=-1 (yalniz programla odaklanir)" : "odaklanabilir degil";
  console.log(`  ${o.ad.padEnd(18)} ${neden}`);
}
```

```
sekme sirasi:
  1. button#disaAktar   tabindex=1
  2. a.atlama-bagi      tabindex=yok
  3. input#suzgec       tabindex=yok
  4. button#suz         tabindex=yok
  5. button.sil[T-01]   tabindex=yok
  6. div.satir-kabi     tabindex=0
sirada olmayanlar:
  div#ozet           tabindex=-1 (yalniz programla odaklanir)
  span.rozet         odaklanabilir degil
  button.sil[T-02]   devre disi
  button#gonder      gizli
```

Üç kural çıktıda görünür.

**Sıfır değeri ögeyi sıraya sokar, yerini değiştirmez.** Doğal olarak odak almayan bir
kapsayıcı böylece sekme durağı olur ve belge sırasındaki yerini korur.

**Eksi bir değeri ögeyi sıradan çıkarır ama odaklanabilir bırakır.** Sekme tuşu üzerinden
geçmez; program odağı oraya taşıyabilir. Bir hata özetine ya da açılan panele odak vermek
bu değerle mümkün olur.

**Artı değerler sırayı bozar.** Çıktının ilk satırı bunu gösterir: dışa aktarma düğmesi
belgede dördüncü sıradadır, sekme sırasında birincidir. Sayfanın atlama bağı ikinci sıraya
düşmüştür. Artı değerler belgedeki bütün diğer duraklardan önce gelir; sayfaya sonradan
eklenen her bileşen bu sıralamayı yeniden düşünmek zorunda kalır. WCAG 2.4.3 ölçütünün
istediği anlamlı sıra, işaretlemenin sırasını doğru kurmakla sağlanır; artı değerlerle
değil.

## Odak Olayları ve Programlı Odak

Odak değişimi dört olay üretir ve bunlar iki çift hâlinde tanımlıdır. Olay Modeli
dersinde belirtildiği gibi odak alma ve odak kaybetme olayları **kabarmaz**; aynı bilgiyi
veren kabaran bir çift ayrıca tanımlıdır. Bir formdaki bütün alanların odak değişimini tek
dinleyiciyle izlemek isteyen kod, kabaran çifti kullanmak ya da yakalama kipine kaydolmak
zorundadır; Olay Devri dersinde konan kural burada işler.

Odak olayları, odağı **bırakan** ve **alan** ögeyi birlikte bildirir. Bir alandan
çıkıldığında odağın nereye gittiği bu bilgiyle okunur ve iki durum ayırt edilir: odak
formun içinde başka bir alana geçmiştir ya da formun tamamından çıkılmıştır. Alan
doğrulamasını yalnızca ikinci durumda çalıştırmak, kullanıcıyı her alan geçişinde hata
iletisiyle karşılamaktan kurtarır.

Odağı program taşıdığında iki sorumluluk doğar. Birincisi, odak taşınan ögenin
görünmesidir; tarayıcı odaklanan ögeyi görünür alana kaydırır ve bu kaydırma bir sayfa
sıçraması olarak algılanabilir. İkincisi, **odağın kaybolmamasıdır**: odaklı bir öge
ağaçtan çıkarıldığında odak belgenin köküne düşer ve sekme tuşu dolaşıma en baştan başlar.
Bir satırı silen kod, silmeden önce odağın nereye gideceğine karar vermelidir — komşu
satıra ya da listenin kendisine.

Bir üçüncü durum odağı **kapatmayı** gerektirir. Açılan bir iletişim kutusu, arkasındaki
sayfaya sekme tuşuyla geçilmesini engeller; odak kutunun içinde döner. Bu düzenin
kurulması sırasında WCAG 2.1.2 ölçütü bir sınır koyar: kullanıcı klavyeyle girdiği yerden
klavyeyle çıkabilmelidir. Çıkışı olmayan bir odak kuşatması erişilebilirlik hatasıdır.

## Klavye Olayları

Tuş basımı iki olay üretir: tuşa basıldığında ve tuş bırakıldığında. Basılı tutulan tuş,
işletim sisteminin tekrar aralığına göre yeni basım olayları üretir; olay nesnesindeki
tekrar bayrağı bu olayları ilk basımdan ayırır. Sayaç artıran bir tuş kısayolu, tekrarı
saymak isteyip istemediğine göre bu bayrağı okur.

Olay nesnesi tuşu iki ayrı alanla bildirir ve ikisinin ayrımı kritiktir.

**Anlam alanı** tuşun ürettiği değeri verir: `a`, `Enter`, `ArrowDown`, `Escape`.
Kullanıcının klavye düzenine ve basılı değiştiricilere göre değişir; büyük harf ile küçük
harf farklı değerlerdir.

**Konum alanı** tuşun klavyedeki fiziksel yerini verir. Düzen değişse de aynı kalır.

Seçim kuralı şudur: kısayol bir harfin anlamına dayanıyorsa anlam alanı, tuşun elin
altındaki yerine dayanıyorsa konum alanı okunur. Anlam alanına dayanan kod, farklı
düzenlerde farklı tuşlara düşer; konum alanına dayanan kod ise kullanıcının gördüğü harfle
uyuşmayabilir.

Metin girişini tuş olaylarından türetmek ayrı bir hatadır. Çince, Japonca ve Korece
girişte kullanılan **birleştirme (composition)** düzeneğinde kullanıcı birden çok tuşa
basarak tek bir karakter üretir; ara aşamada alanın içeriği tuşlarla örtüşmez. Aynı biçimde
yapıştırma, sesle giriş ve otomatik doldurma tuş olayı üretmez. Alanın içeriğini öğrenmenin
tek güvenilir yolu, girdi olaylarını dinlemektir; bu Form Olayları dersinin konusudur.

## Grup İçi Gezinme

Ölçüm tablosunun her satırında bir düğme varsa, sekme tuşu bütün satırları tek tek dolaşır;
yüz satırlık tabloda tablodan çıkmak yüz tuşa bakar. Yerleşik çözüm, grubu tek sekme durağı
yapıp grup içinde ok tuşlarıyla gezinmektir. Düzenin adı **dönen sekme durağı (roving
tabindex)** dır: grupta her an tek bir ögenin `tabindex` değeri sıfırdır, diğerleri eksi
birdir; ok tuşu hem odağı hem de sıfır değerini taşır.

```js
// donen.mjs — grup icinde tek sekme duragi birakan odak yonetimi
const satirlar = ["T-01", "T-02", "T-03", "T-04"];
let etkin = 0;          // gruptaki tek sekme duragi
let odak = "grup disi"; // o an odagi tutan oge

const duraklar = () => satirlar.map((ad, i) => `${ad}:${i === etkin ? 0 : -1}`).join(" ");

function tus(ad) {
  const sonuc = { tus: ad, onlendi: false };
  if (odak === "grup disi") {
    if (ad === "Tab") odak = satirlar[etkin];   // gruba giris: tarayicinin kendi davranisi
    return sonuc;
  }
  switch (ad) {
    case "ArrowDown": etkin = (etkin + 1) % satirlar.length; break;
    case "ArrowUp":   etkin = (etkin - 1 + satirlar.length) % satirlar.length; break;
    case "Home":      etkin = 0; break;
    case "End":       etkin = satirlar.length - 1; break;
    case "Tab":       odak = "grup disi"; return sonuc;   // varsayilan davranis birakilir
    default:          return sonuc;                        // is yapilmadi, iptal istenmez
  }
  odak = satirlar[etkin];
  sonuc.onlendi = true;   // ok tuslarinin kaydirma davranisi iptal edilir
  return sonuc;
}

console.log("baslangic:", odak.padEnd(9), "|", duraklar());
for (const ad of ["Tab", "ArrowDown", "ArrowDown", "End", "Home", "ArrowUp", "x", "Tab"]) {
  const sonuc = tus(ad);
  console.log(
    sonuc.tus.padEnd(9),
    "odak:", odak.padEnd(9),
    "| iptal:", String(sonuc.onlendi).padEnd(5),
    "|", duraklar(),
  );
}
```

```
baslangic: grup disi | T-01:0 T-02:-1 T-03:-1 T-04:-1
Tab       odak: T-01      | iptal: false | T-01:0 T-02:-1 T-03:-1 T-04:-1
ArrowDown odak: T-02      | iptal: true  | T-01:-1 T-02:0 T-03:-1 T-04:-1
ArrowDown odak: T-03      | iptal: true  | T-01:-1 T-02:-1 T-03:0 T-04:-1
End       odak: T-04      | iptal: true  | T-01:-1 T-02:-1 T-03:-1 T-04:0
Home      odak: T-01      | iptal: true  | T-01:0 T-02:-1 T-03:-1 T-04:-1
ArrowUp   odak: T-04      | iptal: true  | T-01:-1 T-02:-1 T-03:-1 T-04:0
x         odak: T-04      | iptal: false | T-01:-1 T-02:-1 T-03:-1 T-04:0
Tab       odak: grup disi | iptal: false | T-01:-1 T-02:-1 T-03:-1 T-04:0
```

Dört davranış çıktıda okunur. Gruba giriş tarayıcının kendi sekme davranışıdır ve iptal
edilmez. Ok tuşları odağı taşır ve yalnızca bu tuşlarda iptal istenir; ok tuşlarının
sayfayı kaydırma davranışı yerine grup içi gezinme konmuştur. Son satırdan önceki `x`
satırı, ele alınmayan tuşlarda iptal istenmediğini gösterir — yazma, kısayollar ve tarayıcı
davranışları etkilenmez. Son sekme tuşu grubu terk eder ve gruptaki durak, en son
kullanılan satırda kalır; kullanıcı geri döndüğünde bıraktığı yerden devam eder.

## Özet

- Belgede her an en çok bir öge girdiyi alır; odaklanabilirlik doğal odak alma, görünürlük
  ve etkinlik koşullarına bağlıdır.
- Sıfır `tabindex` ögeyi belge sırasındaki yerinde sıraya sokar, eksi bir sıradan çıkarır
  ama programlı odağa açık bırakır, artı değerler bütün sıranın önüne geçerek düzeni bozar.
- Odak olaylarının kabarmayan çifti yalnızca hedefte görülür; devir için kabaran çift ya da
  yakalama kipi kullanılır. Olaylar odağı bırakan ve alan ögeyi birlikte bildirir.
- Odaklı bir öge ağaçtan çıkarılırsa odak kökten yeniden başlar; silme ve kapatma işlemleri
  odağın nereye gideceğine önceden karar vermelidir.
- Tuş olayları anlamı ve fiziksel konumu ayrı alanlarda bildirir; metin girişi tuş
  olaylarından türetilemez.
- Dönen sekme durağı düzeninde grupta tek durak bulunur, ok tuşları odağı ve durağı
  birlikte taşır, ele alınmayan tuşlarda varsayılan davranış korunur.

## Sonraki Adım

Bu ders metin girişini öğrenmenin tek güvenilir yolunun tuş olayları olmadığını söyledi ve
gerçek yolu sonraya bıraktı. Sayfadaki form yalnızca metin de toplamaz: ölçüm değeri
sayıdır, tarih bir takvim denetiminden gelir, istasyon kodu bir listeden seçilir. Her
denetim değeri farklı anlarda bildirir — kimi her tuşta, kimi alan terk edildiğinde. Bunun
üstünde bir de gönderim vardır: tarayıcı alanları toplar, kısıtları sınar ve isteği kurar.
Sonraki ders bu akışı, hangi olayın hangi anı bildirdiğini ve doğrulamanın nereye
yerleştiğini inceler.
