---
title: 'Karşıtlık ve Erişilebilirlik'
source: 'https://academia.sh/tr/kurslar/arayuz-temelleri/karsitlik-ve-erisilebilirlik'
course: 'Arayüz Tasarımının Temelleri'
language: tr
updated: '2026-08-17T18:09:36+00:00'
license: 'CC BY-SA 4.0'
---

# Karşıtlık ve Erişilebilirlik

Kontrast oranı formülünün tanımı ve sınırları, eşikten renge ters hesap, büyük metin sınırının süreksizliği ve katalog arayüzünün tamamının toplu denetimi.

Son iki derste 4.5 ve 3.0 sayıları her hesapta göründü. Bu sayılar kursun keyfî seçtiği
ölçütler değil; nasıl ölçüleceği, hangi ögeleri kapsadığı ve hangi durumlarda muaf tutulduğu
tanımlanmış eşiklerdir. Bu ders eşiklerin nereden geldiğini, hangi noktada tasarımı
kısıtladığını ve katalog arayüzünün tamamının bunlara karşı nasıl denetleneceğini ele alır.

Ders adındaki iki sözcük iki ayrı şeye işaret eder. **Karşıtlık**, ilk derste tanıtılan
algısal ilkedir: bir ögeyi çevresinden ayıran fark. **Kontrast oranı** ise bu farkın
ölçülen niceliğidir. Karşıtlık bir tasarım aracıdır ve boyutta, ağırlıkta, biçimde ve
konumda da kurulabilir; kontrast oranı yalnızca iki rengin bağıl parlaklıkları arasındaki
ilişkiyi verir.

## Formül ve Sınırları

**Kontrast oranı (contrast ratio)** iki rengin bağıl parlaklıklarından hesaplanır:

$$
K = \frac{L_1 + 0.05}{L_2 + 0.05}
$$

Burada $L_1$ açık olanın, $L_2$ koyu olanın bağıl parlaklığıdır. Paydadaki 0.05 sabiti,
ekran yüzeyinden gelen ortam yansımasını temsil eder; bu sabit olmasaydı siyahın parlaklığı
sıfır olduğu için oran sonsuza giderdi.

```js
// esik.mjs — kontrast orani formulunun sinirlari, esikten renge ters hesap ve buyuk metin siniri

function kanal(v) {
  const s = v / 255;
  return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
}
const parlaklik = ([r, g, b]) => 0.2126 * kanal(r) + 0.7152 * kanal(g) + 0.0722 * kanal(b);
function kontrast(a, b) {
  const [x, y] = [parlaklik(a), parlaklik(b)].sort((p, q) => q - p);
  return (x + 0.05) / (y + 0.05);
}
function hslRgb(h, s, l) {
  s /= 100; l /= 100;
  const k = (n) => (n + h / 30) % 12;
  const a = s * Math.min(l, 1 - l);
  const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
  return [f(0), f(8), f(4)].map((v) => Math.round(v * 255));
}
const onaltilik = (rgb) => "#" + rgb.map((v) => v.toString(16).padStart(2, "0")).join("");

const SIYAH = [0, 0, 0];
const BEYAZ = [255, 255, 255];
console.log(`parlaklik(siyah) = ${parlaklik(SIYAH).toFixed(4)}   parlaklik(beyaz) = ${parlaklik(BEYAZ).toFixed(4)}`);
console.log(`kontrast(siyah, beyaz) = ${kontrast(SIYAH, BEYAZ).toFixed(2)}:1   (formulun ust siniri)`);
console.log(`kontrast(beyaz, beyaz) = ${kontrast(BEYAZ, BEYAZ).toFixed(2)}:1   (alt siniri)`);

// Ters hesap: beyaz zemin uzerinde bir esigi saglayan en yuksek bagil parlaklik
console.log("\nesik  izin verilen en yuksek bagil parlaklik  esdeger gri (0-255)");
function griden(l) {
  let alt = 0, ust = 255;
  for (let i = 0; i < 40; i++) {
    const orta = (alt + ust) / 2;
    if (parlaklik([orta, orta, orta]) < l) alt = orta; else ust = orta;
  }
  return (alt + ust) / 2;
}
for (const esik of [3.0, 4.5, 7.0]) {
  const enYuksek = 1.05 / esik - 0.05;
  console.log(`${esik.toFixed(1).padStart(4)}  ${enYuksek.toFixed(4).padStart(38)}  ${griden(enYuksek).toFixed(1).padStart(18)}`);
}

// Formul yalniz parlakligi gorur: farkli tonlarda ayni orani veren renkler
console.log("\nton  aciklik  onaltilik  bagil parlaklik  beyaza karsi");
const HEDEF = 1.05 / 4.5 - 0.05;
for (const ton of [8, 42, 145, 214, 268]) {
  let alt = 0, ust = 100;
  for (let i = 0; i < 40; i++) {
    const orta = (alt + ust) / 2;
    if (parlaklik(hslRgb(ton, 60, orta)) < HEDEF) alt = orta; else ust = orta;
  }
  const l = (alt + ust) / 2;
  const rgb = hslRgb(ton, 60, l);
  console.log(
    `${String(ton).padStart(3)} ${l.toFixed(2).padStart(8)}%  ${onaltilik(rgb)}  ${parlaklik(rgb).toFixed(4).padStart(15)}  ${kontrast(rgb, BEYAZ).toFixed(2).padStart(11)}:1`
  );
}

// WCAG "buyuk metin" siniri: 18pt ya da kalin 14pt
const PT_PX = 96 / 72;
console.log(`\n18pt = ${(18 * PT_PX).toFixed(2)} px, 14pt = ${(14 * PT_PX).toFixed(2)} px`);
const buyukMu = (px, agirlik) => px >= 18 * PT_PX || (agirlik >= 700 && px >= 14 * PT_PX);
console.log("px  agirlik  buyuk metin  gecerli esik");
for (const [px, ag] of [[16, 400], [18, 700], [19, 700], [20, 400], [23, 400], [24, 400], [31, 700]]) {
  const b = buyukMu(px, ag);
  console.log(`${String(px).padStart(2)} ${String(ag).padStart(8)}  ${(b ? "evet" : "hayir").padStart(11)}  ${(b ? "3.0" : "4.5").padStart(12)}`);
}
```

```
parlaklik(siyah) = 0.0000   parlaklik(beyaz) = 1.0000
kontrast(siyah, beyaz) = 21.00:1   (formulun ust siniri)
kontrast(beyaz, beyaz) = 1.00:1   (alt siniri)

esik  izin verilen en yuksek bagil parlaklik  esdeger gri (0-255)
 3.0                                  0.3000               148.9
 4.5                                  0.1833               118.7
 7.0                                  0.1000                89.0

ton  aciklik  onaltilik  bagil parlaklik  beyaza karsi
  8    51.12%  #cd4c38           0.1843         4.48:1
 42    35.91%  #927225           0.1828         4.51:1
145    33.21%  #22884c           0.1847         4.47:1
214    50.49%  #3577cd           0.1836         4.50:1
268    59.44%  #935ad6           0.1837         4.49:1

18pt = 24.00 px, 14pt = 18.67 px
px  agirlik  buyuk metin  gecerli esik
16      400        hayir           4.5
18      700        hayir           4.5
19      700         evet           3.0
20      400        hayir           4.5
23      400        hayir           4.5
24      400         evet           3.0
31      700         evet           3.0
```

Birinci blok formülün aralığını veriyor: en düşük 1:1, en yüksek 21:1. Bu aralık yüzde
değil oran ölçüsüdür; 10:1 ile 20:1 arasındaki fark, 2:1 ile 4:1 arasındaki farkla aynı
katsayıdır ama gözle bakıldığında aynı büyüklükte değildir. Oranın kendisi doğrusal bir
algı ölçüsü değildir.

İkinci blok ters hesabı veriyor ve tasarım tarafında doğrudan kullanılır. Beyaz zemin
üzerinde 4.5 eşiğini sağlayan bir metin renginin bağıl parlaklığı en fazla 0.1833 olabilir;
gri karşılığı 255 üzerinden yaklaşık 118.7. Bu, "metin rengi ne kadar açık olabilir"
sorusunun sayısal yanıtıdır ve bir rengi denemek yerine doğrudan üretmeye yarar.

Üçüncü blok formülün en önemli sınırını gösteriyor. Beş farklı ton, hepsi beyaza karşı
yaklaşık 4.5 kontrast üretiyor; ama bunu tutturdukları HSL açıklık değerleri yüzde 33.21 ile
yüzde 59.44 arasında dağılıyor. Formül tonu görmez, yalnızca bağıl parlaklığı görür. Bunun
iki sonucu var: aynı eşiği farklı tonlarda tutturmak farklı açıklık gerektirir, ve iki renk
eşiği geçse bile birbirinden ayırt edilebilir olduklarını göstermez — bu, önceki dersteki
bulgunun genel biçimidir.

Dördüncü blok bir başka sınırı, bir süreksizliği gösteriyor. Ölçüt metni iki kovaya ayırır:
büyük ve büyük olmayan. Sınır 18 punto, kalın yazıda 14 puntodur; piksel karşılıkları 24 ve
18.67. Bunun sonucu, 18 piksellik kalın bir metnin 4.5 eşiğine, 19 piksellik kalın bir
metnin ise 3.0 eşiğine tabi olmasıdır. Bir piksellik boyut değişikliği gereken kontrastı
üçte bir oranında düşürüyor. Ölçüt sürekli bir işlev değil, basamaklı bir kuraldır.

## Hangi Eşik Nereden Geliyor

Eşikler WCAG ölçütlerinde tanımlıdır. Dört ölçüt bu kursun kararlarını doğrudan bağlar:

- **1.4.1 Renk Kullanımı.** Renk, bilgi aktarmanın, bir eylemi belirtmenin ya da bir yanıtı
  ayırt etmenin tek görsel yolu olamaz. Önceki dersteki metin, simge ve konum kanalları bu
  ölçütün karşılığıdır. Bu ölçütün bir eşiği yoktur; bir yapı koşuludur.
- **1.4.3 Kontrast (En Az).** Metin ve metin görüntüleri için en az 4.5:1; büyük metin için
  3:1.
- **1.4.6 Kontrast (Gelişmiş).** Aynı ayrım için 7:1 ve büyük metinde 4.5:1. Bu daha yüksek
  düzeydir; katalog arayüzünün gövde metni nötr 900 basamağında 15.74:1 taşıdığı için zaten
  karşılanır, ancak ikincil metinde karşılanmaz.
- **1.4.11 Metin Dışı Kontrast.** Bir bileşeni ya da durumunu tanımlamak için gereken görsel
  bilgi ile komşu renkler arasında en az 3:1. Kenarlık, odak halkası ve simge çizgileri bu
  ölçüte girer.

İki muafiyet vardır ve ikisi de karar noktasıdır. Etkin olmayan bileşenler, yani devre dışı
bırakılmış denetimler, 1.4.3 kapsamı dışındadır. Salt süsleme amaçlı ve bilgi taşımayan
metin de kapsam dışıdır. Muafiyet bir izin belgesi değildir: bir metin okunmuyorsa ölçüt
onu muaf tutsa bile arayüz o bilgiyi vermiyordur.

## Arayüzün Tamamını Denetlemek

Tek tek eşleşmelere bakmak yetmez, çünkü kaçırılan eşleşme fark edilmez. Denetim, arayüzde
gerçekten oluşan bütün ön plan–zemin çiftlerinin listelenmesiyle yapılır.

```js
// denetim.mjs — katalog arayuzunun tamaminin esiklere karsi toplu denetimi

function hslRgb(h, s, l) {
  s /= 100; l /= 100;
  const k = (n) => (n + h / 30) % 12;
  const a = s * Math.min(l, 1 - l);
  const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
  return [f(0), f(8), f(4)].map((v) => Math.round(v * 255));
}
function kanal(v) {
  const s = v / 255;
  return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
}
const parlaklik = ([r, g, b]) => 0.2126 * kanal(r) + 0.7152 * kanal(g) + 0.0722 * kanal(b);
function kontrast(a, b) {
  const [x, y] = [parlaklik(a), parlaklik(b)].sort((p, q) => q - p);
  return (x + 0.05) / (y + 0.05);
}

const ACIKLIK = { "000": 100, "050": 97, 100: 92, 200: 84, 300: 74, 400: 62, 500: 50, 600: 40, 700: 31, 800: 22, 900: 14 };
const TON = { notr: [214, 8], ana: [214, 62], hata: [8, 68] };
const renk = (aile, b) => hslRgb(TON[aile][0], TON[aile][1], ACIKLIK[b]);

const ROL = {
  "yuzey":            ["notr", "000"],
  "yuzey-ikincil":    ["notr", "050"],
  "kenarlik":         ["notr", "500"],
  "metin-birincil":   ["notr", "900"],
  "metin-ikincil":    ["notr", "600"],
  "metin-devredisi":  ["notr", "400"],
  "eylem-ana":        ["ana", "600"],
  "eylem-ana-uzeri":  ["notr", "000"],
  "odak-halkasi":     ["ana", "500"],
  "secili-zemin":     ["ana", "100"],
  "hata-metni":       ["hata", "600"],
};

const PT_PX = 96 / 72;
const buyukMu = (px, ag) => px >= 18 * PT_PX || (ag >= 700 && px >= 14 * PT_PX);

// tur: "metin" | "metin-disi"
const DENETIM = [
  ["sayfa basligi",        "metin-birincil",  "yuzey",         "metin", 31, 700],
  ["kayit basligi",        "metin-birincil",  "yuzey",         "metin", 20, 600],
  ["yazar adi",            "metin-ikincil",   "yuzey",         "metin", 16, 400],
  ["ustveri (raf kodu)",   "metin-ikincil",   "yuzey-ikincil", "metin", 13, 400],
  ["odunc al dugmesi",     "eylem-ana-uzeri", "eylem-ana",     "metin", 16, 600],
  ["arama alani yer tut.", "metin-devredisi", "yuzey",         "metin", 16, 400],
  ["devre disi dugme",     "metin-devredisi", "yuzey-ikincil", "metin", 16, 600],
  ["hata iletisi",         "hata-metni",      "yuzey",         "metin", 13, 400],
  ["alan kenarligi",       "kenarlik",        "yuzey",         "metin-disi", 0, 0],
  ["odak halkasi",         "odak-halkasi",    "yuzey",         "metin-disi", 0, 0],
  ["secili satir zemini",  "secili-zemin",    "yuzey",         "metin-disi", 0, 0],
  ["secili satirda yazar", "metin-ikincil",   "secili-zemin",  "metin", 16, 400],
];

console.log("oge                    on plan           zemin           tur         esik  olculen  sonuc");
let kalan = 0;
for (const [oge, on, zemin, tur, px, ag] of DENETIM) {
  const esik = tur === "metin-disi" ? 3.0 : buyukMu(px, ag) ? 3.0 : 4.5;
  const k = kontrast(renk(...ROL[on]), renk(...ROL[zemin]));
  const gecti = k >= esik;
  if (!gecti) kalan++;
  console.log(
    `${oge.padEnd(22)} ${on.padEnd(17)} ${zemin.padEnd(15)} ${tur.padEnd(11)} ${esik.toFixed(1).padStart(4)} ${k.toFixed(2).padStart(8)}  ${gecti ? "gecti" : "KALDI"}`
  );
}
console.log(`\ntoplam ${DENETIM.length} eslesme, ${kalan} tanesi esigi gecmiyor`);

// Kalanlar icin: ayni ailede esigi saglayan ilk basamak
console.log("\nkalan eslesme      simdiki basamak  gereken en acik basamak");
for (const [oge, on, zemin, tur, px, ag] of DENETIM) {
  const esik = tur === "metin-disi" ? 3.0 : buyukMu(px, ag) ? 3.0 : 4.5;
  if (kontrast(renk(...ROL[on]), renk(...ROL[zemin])) >= esik) continue;
  const [aile] = ROL[on];
  const zeminRgb = renk(...ROL[zemin]);
  const uygun = Object.keys(ACIKLIK).find((b) => kontrast(renk(aile, b), zeminRgb) >= esik);
  console.log(
    `${oge.padEnd(18)} ${(ROL[on][0] + "-" + ROL[on][1]).padEnd(16)} ${uygun ? aile + "-" + uygun + " (" + kontrast(renk(aile, uygun), zeminRgb).toFixed(2) + ":1)" : "ailede yok"}`
  );
}

// Secili satir zemini koyulastirilirsa uzerindeki metin ne olur?
console.log("\nsecili zemin  zemin/yuzey  uzerindeki metin (notr-600)  metin esigi 4.5");
for (const b of ["100", "200", "300", "400"]) {
  const zemin = renk("ana", b);
  const kz = kontrast(zemin, renk(...ROL["yuzey"]));
  const km = kontrast(renk("notr", "600"), zemin);
  console.log(
    `${("ana-" + b).padEnd(13)} ${kz.toFixed(2).padStart(11)}:1 ${km.toFixed(2).padStart(28)}:1  ${km >= 4.5 ? "gecti" : "KALDI"}`
  );
}
```

```
oge                    on plan           zemin           tur         esik  olculen  sonuc
sayfa basligi          metin-birincil    yuzey           metin        3.0    15.74  gecti
kayit basligi          metin-birincil    yuzey           metin        4.5    15.74  gecti
yazar adi              metin-ikincil     yuzey           metin        4.5     5.89  gecti
ustveri (raf kodu)     metin-ikincil     yuzey-ikincil   metin        4.5     5.51  gecti
odunc al dugmesi       eylem-ana-uzeri   eylem-ana       metin        4.5     6.50  gecti
arama alani yer tut.   metin-devredisi   yuzey           metin        4.5     2.74  KALDI
devre disi dugme       metin-devredisi   yuzey-ikincil   metin        4.5     2.56  KALDI
hata iletisi           hata-metni        yuzey           metin        4.5     6.51  gecti
alan kenarligi         kenarlik          yuzey           metin-disi   3.0     4.11  gecti
odak halkasi           odak-halkasi      yuzey           metin-disi   3.0     4.59  gecti
secili satir zemini    secili-zemin      yuzey           metin-disi   3.0     1.23  KALDI
secili satirda yazar   metin-ikincil     secili-zemin    metin        4.5     4.80  gecti

toplam 12 eslesme, 3 tanesi esigi gecmiyor

kalan eslesme      simdiki basamak  gereken en acik basamak
arama alani yer tut. notr-400         notr-600 (5.89:1)
devre disi dugme   notr-400         notr-600 (5.51:1)
secili satir zemini ana-100          ana-400 (3.05:1)

secili zemin  zemin/yuzey  uzerindeki metin (notr-600)  metin esigi 4.5
ana-100              1.23:1                         4.80:1  gecti
ana-200              1.53:1                         3.85:1  KALDI
ana-300              2.06:1                         2.86:1  KALDI
ana-400              3.05:1                         1.94:1  KALDI
```

On iki eşleşmenin üçü kalıyor ve üçünün çözümü birbirinden farklı. Denetimin değeri
başarısızlıkları bulmak değil, her birinin **hangi türden** bir başarısızlık olduğunu
göstermektir.

## Üç Başarısızlık, Üç Farklı Karar

**Arama alanının yer tutucu metni** 2.74 kontrast oranıyla eşiği kaçırıyor. Tablo düzeltmeyi
veriyor: nötr 600 basamağı 5.89 üretir. Ancak bu düzeltme yeni bir sorun yaratır — yer
tutucu metin o basamakta gerçek girdi metninden ayırt edilemez hâle gelir ve kullanıcı
alanın dolu olduğunu sanar. Doğru karar rengi koyulaştırmak değil, yer tutucuyu etiket
olarak kullanmayı bırakmaktır. Alanın adı alanın üstünde kalıcı bir etiket olarak durur;
yer tutucu ya kaldırılır ya da yalnızca biçim örneği verir. Web Temelleri ve HTML kursundaki
etiket–alan ilişkisi dersinde aynı sonuca erişilebilirlik tarafından varılmıştı; burada
aynı sonuca kontrast hesabından varılıyor.

**Devre dışı düğme** 2.56 kontrast oranı taşıyor ve 1.4.3 ölçütü etkin olmayan bileşenleri
muaf tutuyor. Yani bu satır bir uygunluk ihlali değil. Buna rağmen bir karar noktasıdır:
devre dışı düğmenin üzerindeki metin okunamıyorsa, kullanıcı düğmenin ne yaptığını ve neden
kullanılamadığını bilemez. Katalog arayüzünde "Ödünç al" düğmesi kayıt rafta değilken devre
dışı kalıyor; kullanıcının okuması gereken şey tam da o düğmenin metni ve yanındaki
açıklamadır. Muafiyet, düşük kontrastı zorunlu kılmaz; yalnızca serbest bırakır. Karar,
düğmeyi devre dışı bırakmak yerine etkin tutup neden çalışmadığını söylemektir.

**Seçili satır zemini** 1.23 oranıyla kalıyor. Son tablo, koyulaştırarak düzeltmenin neden
işe yaramadığını gösteriyor: zemin ana 400 basamağına taşındığında 3.05 ile eşiği geçiyor,
ama üzerindeki ikincil metin 1.94'e düşerek çok daha ağır bir ihlal üretiyor. Zemini
koyulaştırmak bir sorunu diğeriyle takas ediyor.

Çözüm 1.4.11 ölçütünün kendi ifadesinde saklı: eşik, bir durumu tanımlamak için **gereken**
görsel bilgi için istenir. Seçili olma durumu yalnızca zemin rengiyle bildiriliyorsa zemin o
bilgiyi taşıyor demektir ve eşiğe tabidir. Duruma ikinci bir gösterge eklenirse — satırın
başında 3:1 eşiğini geçen bir dikey çubuk — zemin artık tek taşıyıcı olmaktan çıkar ve soluk
kalabilir. Önceki dersin kuralı burada eşiği karşılamanın yolu hâline geliyor: ikinci kanal
yalnızca dayanıklılık değil, uygunluk da üretir.

## Denetimin Yeri

Bu denetimin sistem kurulurken yapılması, bileşenler yazıldıktan sonra yapılmasından
ucuzdur. Rol tablosu ile eşleşme listesi birlikte tutulduğunda denetim bir veri işleme
işine iner: girdi rol adlarıdır, çıktı geçen ve kalan eşleşmelerdir.

Eşleşme listesinin elle yazılması bir zayıflıktır — arayüze yeni bir eşleşme eklendiğinde
listeye eklenmezse denetim onu görmez. Tasarım tarafında yapılması gereken, listenin var
olması ve her yeni rol eşleşmesinin oraya yazılmasıdır.

## Özet

- Kontrast oranı, iki bağıl parlaklığın 0.05 kaydırmalı oranıdır; aralığı 1:1 ile 21:1
  arasındadır ve doğrusal bir algı ölçüsü değildir.
- Eşikten renge ters hesap yapılabilir: beyaz zeminde 4.5 eşiği, bağıl parlaklığı en fazla
  0.1833 olan bir metin rengine izin verir.
- Formül tonu görmez; aynı oranı veren renkler çok farklı açıklık değerlerinde durur ve
  eşiği geçmeleri birbirlerinden ayırt edilebilir oldukları anlamına gelmez.
- Büyük metin sınırı basamaklı bir kuraldır; 18 ile 19 piksel arasında gereken kontrast
  4.5'ten 3.0'a düşer.
- Denetim tek tek değil, arayüzde gerçekten oluşan bütün ön plan–zemin çiftleri üzerinden
  yapılır; kaçırılan eşleşme fark edilmez.
- Her başarısızlığın çözümü rengi koyulaştırmak değildir: kimi durumda öge kaldırılır, kimi
  durumda ikinci bir gösterge eklenerek renk tek taşıyıcı olmaktan çıkarılır.

## Sonraki Adım

Bu ders bütün eşleşmeleri tek bir zemin ailesine karşı denetledi: açık yüzeyler ve koyu
metin. Aynı arayüz koyu bir temada çalıştığında bu ilişkinin tamamı tersine döner. Ters
çevirme işlemi göründüğü kadar mekanik değildir; rampanın basamaklarını başa baş takas
etmek kontrast oranlarını korumaz ve işlevsel renkler koyu zeminde eşiği kaçırır. Sonraki
ders koyu temayı bir renk listesi olarak değil bir **dönüşüm** olarak kurar, dönüşümün
korunum koşulunu tanımlar ve dönüşümü aynı denetimden geçirir.
