Ders 09 / 19
Aralık ve Boyut Belirteçleri
Aralık ölçeğinin göreli birime çevrilmesi, kök boyutu değiştiğinde metin–boşluk oranının korunması, bileşen yüksekliklerinin hedef boyutu eşikleriyle sınanması ve iç içe köşe yarıçapının türetilmesi.
İçindekiler
Önceki ders satır kutularını aralık ölçeğinin 4 piksellik ızgarasına oturttu ve kayıt kartının toplam yüksekliğinin ızgarada kapandığını gösterdi. Bu hesabın tamamı piksel cinsindendi.
Piksel bir sorun taşır. Kullanıcı tarayıcısının kök yazı boyutunu büyüttüğünde metin büyür; piksel cinsinden yazılmış boşluklar büyümez. Arayüz büyümüş metinle sabit boşluğun karışımına dönüşür ve Yoğunluk Kararları dersinde kurulan denge bozulur. Bu ders ölçü sistemini sayısallaştırır: birim seçimini bir hesaba bağlar, bileşen yüksekliklerini ölçek adımlarından türetir ve türetmenin erişilebilirlik eşiklerini karşılayıp karşılamadığını denetler.
Birim Bir Sunum Ayrıntısı Değildir
Aralık ölçeği bir sayı dizisidir; hangi birimde yazıldığı ölçeğin parçası değil, ölçeğin davranışının parçasıdır. İki aday vardır.
Piksel sabittir. Kök boyutu ne olursa olsun 16 piksel 16 pikseldir. Bu, tasarım zamanındaki hesapları kolay kılar: ızgara uyumu her koşulda korunur.
Göreli birim kök yazı boyutunun katıdır. Kök 16 pikselken 1 birim 16 piksele karşılık gelir; kök 20 piksele çıktığında 20 piksele. Ölçek, kullanıcının yazı boyutu tercihini kendiliğinden devralır.
Seçim bir tercih değil, bir hesabın sonucudur. Aşağıdaki program iki rejimi aynı kart üzerinde karşılaştırır, ardından bileşen ölçülerini türetip eşiklerle denetler.
// olcu.mjs — aralik ve boyut belirteclerinin sayisallastirilmasi, birim secimi ve turetilmis olculer const TABAN_KOK = 16; // varsayilan kok yazi boyutu (px) const OLCEK = [4, 8, 12, 16, 20, 24, 32, 48, 64, 96]; console.log("adim px rem kok 16 px kok 18 px kok 20 px tam sayi (18) tam sayi (20)"); for (let i = 0; i < OLCEK.length; i++) { const px = OLCEK[i]; const rem = px / TABAN_KOK; const k18 = rem * 18; const k20 = rem * 20; console.log( `${String(i + 1).padStart(4)} ${String(px).padStart(3)} ${rem.toFixed(4).padStart(7)} ` + `${px.toFixed(2).padStart(10)} ${k18.toFixed(2).padStart(10)} ${k20.toFixed(2).padStart(10)} ` + `${(Number.isInteger(k18) ? "evet" : "hayir").padStart(14)} ${(Number.isInteger(k20) ? "evet" : "hayir").padStart(14)}` ); } // Birim secimi: kok boyutu buyudugunde metin ile bosluk birlikte buyuyor mu? // Kart: ust bosluk + baslik kutusu + grup ici + iki satir govde + grup ici + ustveri + alt bosluk const KART = { ustBosluk: 16, baslikKutu: 32, grupIci: 8, govdeKutu: 24, govdeSatir: 2, ustveriKutu: 20, altBosluk: 16 }; function kart(kok, aralikRem) { const o = kok / TABAN_KOK; // metin her zaman kok ile olceklenir const b = aralikRem ? o : 1; // bosluklar rem ise olceklenir, px ise sabit kalir const metin = (KART.baslikKutu + KART.govdeKutu * KART.govdeSatir + KART.ustveriKutu) * o; const bosluk = (KART.ustBosluk + KART.grupIci * 2 + KART.altBosluk) * b; return { metin, bosluk, toplam: metin + bosluk, oran: metin / bosluk }; } console.log("\nbirim kok metin (px) bosluk (px) toplam (px) metin/bosluk orani"); for (const [ad, remMi] of [["px ", false], ["rem", true]]) { for (const kok of [16, 18, 20, 24]) { const k = kart(kok, remMi); console.log( `${ad} ${String(kok).padStart(3)} ${k.metin.toFixed(1).padStart(11)} ${k.bosluk.toFixed(1).padStart(12)} ` + `${k.toplam.toFixed(1).padStart(12)} ${k.oran.toFixed(3).padStart(19)}` ); } } // Bilesen yuksekligi turetilir: satir kutusu + 2 x dikey ic bosluk + 2 x kenar kalinligi. // Esikler: WCAG 2.5.8 en az 24 px, WCAG 2.5.5 en az 44 px. const ESIK_TEMEL = 24; const ESIK_GELISMIS = 44; const yukseklik = (kutu, ic, kenar) => kutu + 2 * ic + 2 * kenar; const BILESENLER = [ { ad: "dugme", kutu: 24, ic: 8, kenar: 1 }, { ad: "dugme-buyuk", kutu: 24, ic: 12, kenar: 1 }, { ad: "metin-alani", kutu: 24, ic: 8, kenar: 1 }, { ad: "simge-dugmesi", kutu: 16, ic: 8, kenar: 1 }, { ad: "etiket", kutu: 20, ic: 4, kenar: 0 }, { ad: "liste-satiri", kutu: 24, ic: 12, kenar: 0 }, ]; console.log("\nbilesen kutu ic bosluk kenar yukseklik 2.5.8 (24) 2.5.5 (44)"); for (const b of BILESENLER) { const y = yukseklik(b.kutu, b.ic, b.kenar); console.log( `${b.ad.padEnd(14)} ${String(b.kutu).padStart(4)} ${String(b.ic).padStart(10)} ${String(b.kenar).padStart(6)} ` + `${String(y).padStart(10)} ${(y >= ESIK_TEMEL ? "gecti" : "KALDI").padStart(11)} ${(y >= ESIK_GELISMIS ? "gecti" : "KALDI").padStart(11)}` ); } // 44 px esigini olcek adimlariyla tam olarak tutturmak mumkun mu? console.log("\nkutu 24, kenar 1 -> ic bosluk adimi yukseklik 2.5.5"); for (const ic of OLCEK) { const y = yukseklik(24, ic, 1); if (y > 60) break; console.log(`${String(ic).padStart(35)} ${String(y).padStart(10)} ${(y >= ESIK_GELISMIS ? "gecer" : "kalir").padStart(7)}`); } console.log("kenar 0 ile ayni hesap:"); for (const ic of OLCEK) { const y = yukseklik(24, ic, 0); if (y > 60) break; console.log(`${String(ic).padStart(35)} ${String(y).padStart(10)} ${(y >= ESIK_GELISMIS ? "gecer" : "kalir").padStart(7)}`); } // Ic ice kose yaricapi: ic yaricap = dis yaricap - aradaki ic bosluk. // Tam yuvarlak (999) bir istisnadir: ic ogeye tasinmaz, ic oge kendi yaricapini alir. const YARICAP_OLCEGI = [0, 4, 8, 12, 999]; console.log("\nic ice cift dis yaricap ic bosluk hesaplanan kullanilan olcekte mi"); for (const [ad, disY, ic] of [ ["kart / govde", 8, 16], ["kart / kapak gorseli", 8, 4], ["acilir katman / baslik ", 12, 8], ["acilir katman / dugme", 12, 4], ["etiket / sayac rozeti", 999, 4], ["dugme / simge cercevesi", 4, 2], ]) { const hesap = disY === 999 ? 999 : disY - ic; const kullanilan = disY === 999 ? 999 : Math.max(0, hesap); console.log( `${ad.padEnd(26)} ${String(disY).padStart(11)} ${String(ic).padStart(10)} ${String(hesap).padStart(11)} ` + `${String(kullanilan).padStart(11)} ${YARICAP_OLCEGI.includes(kullanilan) ? "evet" : "HAYIR"}` ); } // Simge olcegi tipografi basamaklarindan degil, satir kutularindan turetilir. console.log("\nsatir kutusu hizalanan simge boyutu olcekte mi"); const SIMGE = [12, 16, 20, 24, 32]; for (const kutu of [20, 24, 32, 36, 48]) { // Simge, satir kutusunun icine ortalanir; kutunun 2/3'unden buyuk simge satiri tasirir. const hedef = Math.floor(((2 / 3) * kutu) / 4) * 4; console.log( `${String(kutu).padStart(12)} ${String(hedef).padStart(22)} ${(SIMGE.includes(hedef) ? "evet" : "HAYIR").padStart(11)}` ); }
adim px rem kok 16 px kok 18 px kok 20 px tam sayi (18) tam sayi (20)
1 4 0.2500 4.00 4.50 5.00 hayir evet
2 8 0.5000 8.00 9.00 10.00 evet evet
3 12 0.7500 12.00 13.50 15.00 hayir evet
4 16 1.0000 16.00 18.00 20.00 evet evet
5 20 1.2500 20.00 22.50 25.00 hayir evet
6 24 1.5000 24.00 27.00 30.00 evet evet
7 32 2.0000 32.00 36.00 40.00 evet evet
8 48 3.0000 48.00 54.00 60.00 evet evet
9 64 4.0000 64.00 72.00 80.00 evet evet
10 96 6.0000 96.00 108.00 120.00 evet evet
birim kok metin (px) bosluk (px) toplam (px) metin/bosluk orani
px 16 100.0 48.0 148.0 2.083
px 18 112.5 48.0 160.5 2.344
px 20 125.0 48.0 173.0 2.604
px 24 150.0 48.0 198.0 3.125
rem 16 100.0 48.0 148.0 2.083
rem 18 112.5 54.0 166.5 2.083
rem 20 125.0 60.0 185.0 2.083
rem 24 150.0 72.0 222.0 2.083
bilesen kutu ic bosluk kenar yukseklik 2.5.8 (24) 2.5.5 (44)
dugme 24 8 1 42 gecti KALDI
dugme-buyuk 24 12 1 50 gecti gecti
metin-alani 24 8 1 42 gecti KALDI
simge-dugmesi 16 8 1 34 gecti KALDI
etiket 20 4 0 28 gecti KALDI
liste-satiri 24 12 0 48 gecti gecti
kutu 24, kenar 1 -> ic bosluk adimi yukseklik 2.5.5
4 34 kalir
8 42 kalir
12 50 gecer
16 58 gecer
kenar 0 ile ayni hesap:
4 32 kalir
8 40 kalir
12 48 gecer
16 56 gecer
ic ice cift dis yaricap ic bosluk hesaplanan kullanilan olcekte mi
kart / govde 8 16 -8 0 evet
kart / kapak gorseli 8 4 4 4 evet
acilir katman / baslik 12 8 4 4 evet
acilir katman / dugme 12 4 8 8 evet
etiket / sayac rozeti 999 4 999 999 evet
dugme / simge cercevesi 4 2 2 2 HAYIR
satir kutusu hizalanan simge boyutu olcekte mi
20 12 evet
24 16 evet
32 20 evet
36 24 evet
48 32 evet
Göreli Birim Tam Sayı Piksel Vermez
Birinci tablo göreli birime geçmenin bedelini gösteriyor. Ölçek adımları kök 16 pikselde tam sayı; kök 20 pikselde de tam sayı. Kök 18 pikselde ise dört adım yarım piksel üretiyor: 4.50, 13.50, 22.50 ve alt adımlar.
Bu bir kusur değil, göreli birimin tanımının sonucudur. Ölçek 16’nın katı olmayan bir kök boyutunda 16’ya bölünmüş kesirler üretir. Sonuç şu iki cümlede özetlenir: ızgara uyumu tasarım zamanının değişmezidir, çalışma zamanının değil. Tasarımcı 4 piksellik ızgarada çalışır; kullanıcı kendi kök boyutunda o ızgaranın ölçeklenmiş hâlini görür ve ızgara oranları korunduğu için görsel sonuç bozulmaz.
Yarım piksel değerlerin kendisi bir sorun üretmez; çizim aşaması bunları kendi çözünürlüğünde yuvarlar. Sorun ancak bir hizanın iki ayrı yoldan hesaplandığı yerde çıkar — bir kenar piksel cinsinden, komşusu göreli birimle yazıldığında yuvarlamalar farklı yönlere gidebilir. Kural bundan çıkar: bir eksende karışık birim kullanılmaz.
Sabit Boşluk Yoğunluğu Bozuyor
İkinci tablo asıl kararı veriyor. Aynı kart iki rejimde, dört farklı kök boyutunda ölçülüyor.
Piksel rejiminde metin yüksekliği kökle birlikte büyüyor — 100’den 150 piksele — ama boşluk 48 pikselde sabit kalıyor. Metin–boşluk oranı 2.083’ten 3.125’e çıkıyor: yüzde 50 artış. Kullanıcı yazıyı büyüttüğünde arayüz orantılı olarak büyümüyor, sıkışıyor.
Göreli birim rejiminde oran dört kök boyutunun hepsinde 2.083. Kart büyüyor, oranlar korunuyor. Yakınlık ve Gruplama dersindeki gruplama oranı ölçütü de bu sayede korunur: grup içi boşluk ile grup sınırı arasındaki oran kök boyutundan bağımsız kalır.
Bu, birim seçimini bir tercih olmaktan çıkarır. Aralık belirteçleri göreli birimde yazılır, çünkü aralığın işi mutlak bir mesafe belirtmek değil, bir oran kurmaktır. Oranı koruyan birim göreli birimdir.
İstisnalar kayda geçirilir. Kenar kalınlığı, odak halkası kalınlığı ve saç teli çizgiler piksel cinsinden kalır: bunların işi oran kurmak değil, görünür bir sınır çizmektir ve kök boyutuyla büyümeleri gerekmez.
Bileşen Yüksekliği Seçilmez, Türetilir
Üçüncü tablo boyut belirteçlerinin nereden geldiğini gösteriyor. Bir bileşenin yüksekliği bir belirteç olarak tanımlanmaz; üç belirteçten hesaplanır.
Bunun gerekçesi Izgara Sistemleri dersindeki sütun genişliği bağıntısının aynısıdır: bağımlı bir büyüklüğü bağımsız bir karar gibi yazmak, ilk değişiklikte tutarsızlık üretir. Düğmenin yüksekliği 42 piksel olarak yazılırsa, satır kutusu değiştiğinde 42 yanlış hâle gelir ama kimse fark etmez.
Denetim iki eşikle yapılıyor. Altı bileşenin hepsi WCAG 2.5.8 ölçütünün istediği 24 pikseli geçiyor; yalnız ikisi 2.5.5 ölçütünün istediği 44 pikseli geçiyor. Standart düğme 42 pikselde kalıyor — eşiğin iki piksel altında.
İki Piksel Ölçek Adımıyla Kapanmıyor
Dördüncü blok bu iki pikselin neden kapatılamadığını gösteriyor. Satır kutusu 24, kenar 1 sabitken iç boşluk ölçek adımlarından seçiliyor: 8 adımı 42 üretiyor, bir sonraki adım olan 12 doğrudan 50’ye çıkıyor. Aradaki 44 değeri ölçekte karşılıksız.
Kenar kalınlığını sıfıra indirmek de çözmüyor: 8 adımı 40, 12 adımı 48 veriyor.
Üç seçenek kalıyor ve üçü de bir bedel taşıyor. Birincisi, iç boşluğu 12’ye çıkarıp düğmeyi 50 piksele büyütmek; bu, Yoğunluk Kararları dersindeki ekran başına kayıt sayısını düşürür. İkincisi, ölçeğe 10 piksellik bir adım eklemek; Aralık Ölçeği dersinde gösterildiği gibi 8 ile 10 arasındaki fark ayırt edilebilirlik eşiğinin altındadır, yani ölçeğe karşılıksız bir adım girer. Üçüncüsü, görsel ölçüyü 42’de bırakıp etkin alanı 44’e genişletmek; Ekran Boyutu ve Girdi Türü dersinde bunun ancak düğmeler arası boşluk da büyütülerek yapılabileceği hesaplanmıştı.
Sistem düzeyinde doğru karar üçüncüsüdür ve kayda geçirilir: standart düğme 42 piksel görünür, etkin alanı 44 pikseldir ve düğmeler arasındaki boşluk en az 20 piksel adımından seçilir. Bu, bir belirtecin tek başına değil, komşusuyla birlikte geçerli olduğu ikinci örnektir; birincisi renk eşleşmeleriydi.
Yarıçap ve Simge Ölçeği de Türetilir
Beşinci tablo iç içe geçmiş köşe yarıçaplarını hesaplıyor. İç yarıçap, dış yarıçaptan aradaki iç boşluğun çıkarılmasıyla bulunur; negatif çıkan değer sıfıra düşer. Bu, iki eğrinin merkezdaş kalmasını sağlar. Kartın gövdesi 16 piksel içeride durduğu için yarıçapı sıfır; kapak görseli 4 piksel içeride olduğu için 4.
Bir satır ölçek dışı çıkıyor: düğme içindeki simge çerçevesi 2 piksel yarıçap istiyor ve yarıçap ölçeğinde 2 yok. Karar iki yönlüdür — ya çerçevenin iç boşluğu 4’e çıkarılıp yarıçap sıfıra indirilir, ya da ölçeğe 2 eklenir. Yinelenme ve Tutarlılık dersinde köşe yarıçapındaki küçük değerlerin ayırt edilemediği ölçülmüştü; bu bulgu birinci seçeneği gösteriyor.
Tam yuvarlak yarıçap bir istisna olarak tanımlanıyor ve türetmeye girmiyor. İçindeki rozet de tam yuvarlak olur; çıkarma işlemi burada anlamsızdır çünkü tam yuvarlak bir yarıçap değil, bir kuraldır.
Son tablo simge ölçeğinin tipografik basamaklardan değil satır kutularından türetildiğini gösteriyor. Simge, satır kutusunun içine ortalanır ve kutunun üçte ikisini aşmamalıdır; aşarsa satırın üstüne ve altına taşar. Beş satır kutusu için hesaplanan beş simge boyutunun hepsi ölçekte karşılık buluyor, çünkü hem satır kutuları hem simge ölçeği 4 piksellik ızgaraya oturtulmuş durumda.
Yazılı Biçim
Aralık ve boyut belirteçleri iki katmanda yazılır; bileşen yükseklikleri hiç yazılmaz, hesapla elde edilir.
:root { /* ilkel: olcek adimlari, goreli birimde */ --adim-1: 0.25rem; --adim-2: 0.5rem; --adim-3: 0.75rem; --adim-4: 1rem; --adim-6: 1.5rem; /* ilkel: piksel kalan olculer */ --kenar-ince: 1px; --kenar-kalin: 2px; --yaricap-1: 4px; --yaricap-2: 8px; /* anlamsal */ --aralik-grup-ici: var(--adim-2); --aralik-blok-arasi: var(--adim-4); --aralik-bolum-arasi: var(--adim-6); } .dugme { --dugme-ic-bosluk-y: var(--aralik-grup-ici); --dugme-ic-bosluk-x: var(--aralik-blok-arasi); padding: var(--dugme-ic-bosluk-y) var(--dugme-ic-bosluk-x); border: var(--kenar-ince) solid currentColor; border-radius: var(--yaricap-1); line-height: 24px; }
Düğmenin yüksekliği bu bildirimde hiçbir yerde yazmıyor. Yükseklik, satır kutusu ile iç boşlukların toplamından çıkar ve bu toplamın 44 piksele ulaşıp ulaşmadığı denetimin sorumluluğudur. Sabit bir yükseklik bildirmek, metin sarıldığında ya da kök boyutu büyüdüğünde içeriğin taşmasına yol açar.
Özet
- Birim seçimi bir sunum ayrıntısı değil, ölçeğin davranışını belirleyen bir karardır: göreli birim kullanıcının kök yazı boyutu tercihini devralır.
- Göreli birim her kök boyutunda tam sayı piksel vermez; ızgara uyumu tasarım zamanının değişmezidir, çalışma zamanının değil. Bir eksende karışık birim kullanılmaz.
- Piksel aralıkla yazılmış bir kartta kök 16’dan 24’e çıktığında metin–boşluk oranı 2.083’ten 3.125’e yükselir; göreli birimde oran dört kök boyutunda da 2.083 kalır.
- Kenar kalınlığı, odak halkası ve saç teli çizgiler piksel kalır, çünkü işleri oran kurmak değil sınır çizmektir.
- Bileşen yüksekliği belirteç olarak yazılmaz; satır kutusu, iç boşluk ve kenar kalınlığından türetilir ve hedef boyutu eşikleriyle denetlenir. Standart düğme 42 pikselde kalır ve 44 eşiği ölçek adımlarıyla tam tutturulamaz; karar görsel ölçüyü koruyup etkin alanı ve komşu boşluğu genişletmektir.
- Köşe yarıçapı iç içe geçmiş ögelerde çıkarmayla türetilir; tam yuvarlak bir değer değil bir kuraldır ve türetmeye girmez. Simge ölçeği tipografik basamaktan değil satır kutusundan türetilir.
Sonraki Adım
Ölçek adımları, tipografi ve boyut belirteçleri tek bir görüntü alanı varsayımıyla kuruldu. Arayüz genişlik değiştirdiğinde sütun sayısı, kenar boşluğu ve oluk da değişir; bu değişimin nerede olacağı şimdiye kadar tek tek verilen kararlardı. Sonraki ders kesme noktalarını bir belirteç kümesine çevirir, her kesme noktasındaki sütun aritmetiğini denetler, aralıkların tutarlı olup olmadığını sınar ve hiçbir düzen kararını değiştirmeyen kesme noktalarını raporlar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.