İçeriğe geç
academia.sh

Ders 11 / 22

Yazı Tipi Seçimi

Seçilebilirlik ile okunabilirliğin ayrımı, yazı tipi sınıflarının vaatleri, x-yüksekliğinden görünen büyüklük hesabı ve abece kapsamı ile karakter ayırt edilebilirliğinin denetlenmesi.

İçindekiler

Önceki ders düzen iskeletini tamamladı: sütunlar, oluklar ve kenar boşlukları ekran genişliğine göre yerini aldı, dokunma hedeflerinin en küçük ölçüsü belirlendi ve imleçle dokunmanın aynı arayüzden farklı şeyler beklediği gösterildi. İskelet ayakta; içine girecek metin ise henüz seçilmedi. Katalog arayüzünün taşıdığı yükün neredeyse tamamı metindir: kayıt başlıkları, yazar adları, raf kodları, ISBN numaraları, tarihler, ödünç alma düğmesinin üzerindeki iki sözcük.

Bu ders tek bir soruyu yanıtlar: bir yazı tipi, beğeniyle değil hangi ölçütlerle seçilir? Ölçütler dört başlıkta toplanır ve üçü hesaplanabilir — görünen büyüklük, abece kapsamı ve karakter ayırt edilebilirliği. Dördüncüsü, ailenin taşıyabileceği hiyerarşi yükü, ilk dersteki iki kanal kuralının doğrudan sonucudur.

Seçilebilirlik ile Okunabilirlik Ayrı Şeylerdir

İki ölçüt sık sık tek sözcükle anılır ve karışır.

Seçilebilirlik (legibility), tek bir karakterin komşularından ayırt edilebilme derecesidir. Bir raf kodundaki I harfinin 1 rakamından ayrılıp ayrılmadığı bir seçilebilirlik sorusudur. Karakter düzeyinde ölçülür ve yazı tipinin kendi özelliğidir.

Okunabilirlik (readability), bir metin bloğunun akıcı okunma derecesidir. Satır uzunluğu, satır aralığı, hizalama ve kontrast oranı bu ölçüte girer. Blok düzeyinde ölçülür ve yazı tipinin değil, tasarımın özelliğidir.

Ayrımın pratik sonucu şudur: seçilebilirlik sorunu yazı tipi değiştirilerek çözülür, okunabilirlik sorunu ise düzen değiştirilerek. Katalog arayüzünde raf kodunun yanlış okunması birinci sınıfa, arama sonuçları listesinin göz yorması ikinci sınıfa girer. İkisi aynı çözümle iyileşmez.

Katalog arayüzünün iki ayrı metin kütlesi vardır ve ölçütleri farklıdır. Sonuç listesi ile üstveri alanları kısa, taranan, birbirine benzeyen dizgilerden oluşur; buralarda seçilebilirlik belirleyicidir. Kayıt ayrıntısındaki özet paragrafı ise sürekli okunur; orada okunabilirlik belirleyicidir.

Sınıflar ve Vaat Ettikleri

Yazı tipleri, taşıdıkları biçim özelliklerine göre sınıflara ayrılır. Sınıf, ürün adı vermeden konuşmayı sağlar ve daha önemlisi, her sınıfın ne vaat ettiğini söyler.

  • Tırnaklı (serif). Harf uçlarında bitiş çizgileri taşır. Bu çizgiler yatay bir akış ipucu üretir; uzun sürekli metinde işe yarar. Küçük boyutlarda bitiş çizgileri incelir ve düşük çözünürlükte kaybolabilir.
  • Tırnaksız (sans-serif). Bitiş çizgisi yoktur. Küçük boyutlarda ve arayüz etiketlerinde daha kararlıdır; harf gövdeleri sadeleştiği için birbirine benzeyen karakterlerin ayrımı zayıflayabilir.
  • Eşit aralıklı (monospace). Her karakter aynı ilerleme genişliğini kaplar. Sütun hizası gerektiren yerlerde — raf kodu, ISBN, tarih — hizalamayı ücretsiz verir. Sürekli metinde sözcük şekilleri bozulduğu için okuma hızını düşürür.
  • Değişken yazı tipi (variable font). Tek dosyada sürekli bir ağırlık ekseni taşır; her ağırlık için ayrı dosya indirilmesi gerekmez. Sağladığı şey yeni bir biçim değil, ağırlık kanalının ucuzlamasıdır.

CSS tarafında bu sınıfların karşılığı genel aile anahtar sözcükleridir: serif, sans-serif, monospace. Bunlar CSS ile Görsel Sunum kursunda aile listesinin son öğesi olarak tanıtılmıştı; tasarım tarafında ise doğrudan bir sınıf kararıdır.

Katalog arayüzünün kararı bu ayrımdan çıkar: gövde ve başlıklar için tek bir tırnaksız aile, raf kodu ve ISBN alanları için eşit aralıklı bir aile. İki aile, çünkü iki farklı iş var; üç aile ise savunulamaz, çünkü üçüncü işin adı konamaz.

Nominal Boyut Görünen Büyüklük Değildir

Aynı boyutta yazılmış iki yazı tipi aynı büyüklükte görünmez. Nominal boyut em kutusunun ölçüsüdür; gözün büyüklük olarak algıladığı şey ise küçük harflerin gövde yüksekliği, yani x-yüksekliği (x-height) değeridir. Yazı tipi dosyası bu ölçüyü kendi metaverisinde em birimi cinsinden bildirir, dolayısıyla hesaplanabilir.

// xyukseklik.mjs — bildirilen yazi tipi olculerinden gorunen buyukluk hesabi

// Her yazi tipi dosyasi olculerini em birimi cinsinden bildirir (burada em = 1000 birim).
// Asagidakiler uc aday ailenin bildirdigi olculerdir.
const adaylar = [
  { ad: "aday-1", xYukseklik: 480, buyukHarf: 700, cikinti: 750, inis: 250 },
  { ad: "aday-2", xYukseklik: 520, buyukHarf: 715, cikinti: 800, inis: 230 },
  { ad: "aday-3", xYukseklik: 548, buyukHarf: 730, cikinti: 776, inis: 275 },
];

const EM = 1000;
const TABAN_PX = 16; // govde metni icin secilen nominal boyut

console.log("aday      x/em    x-yuksekligi  buyuk harf  x/buyuk harf");
for (const a of adaylar) {
  const xOran = a.xYukseklik / EM;
  const xPx = xOran * TABAN_PX;
  const bhPx = (a.buyukHarf / EM) * TABAN_PX;
  console.log(
    `${a.ad.padEnd(9)} ${xOran.toFixed(3)}   ${xPx.toFixed(2).padStart(9)} px ${bhPx.toFixed(2).padStart(8)} px  ${(a.xYukseklik / a.buyukHarf).toFixed(3)}`
  );
}

// Ayni gorunen buyuklugu tutturmak icin gereken nominal boyut.
// Hedef, aday-3'un 16 pikselde urettigi x-yuksekligidir.
const hedefX = (548 / EM) * TABAN_PX;
console.log(`\nhedef x-yuksekligi: ${hedefX.toFixed(2)} px (aday-3, 16px)`);
console.log("aday      esdeger nominal boyut   fark");
for (const a of adaylar) {
  const gereken = hedefX / (a.xYukseklik / EM);
  const fark = gereken - TABAN_PX;
  console.log(
    `${a.ad.padEnd(9)} ${gereken.toFixed(2).padStart(18)} px ${(fark >= 0 ? "+" : "") + fark.toFixed(2)} px`
  );
}

// Satir kutusunun tasidigi dikey olcu: cikinti + inis.
console.log("\naday      cikinti+inis (em)   esdeger boyutta (px)");
for (const a of adaylar) {
  const toplam = (a.cikinti + a.inis) / EM;
  const gereken = hedefX / (a.xYukseklik / EM);
  console.log(
    `${a.ad.padEnd(9)} ${toplam.toFixed(3).padStart(16)} ${(toplam * gereken).toFixed(2).padStart(21)}`
  );
}
aday      x/em    x-yuksekligi  buyuk harf  x/buyuk harf
aday-1    0.480        7.68 px    11.20 px  0.686
aday-2    0.520        8.32 px    11.44 px  0.727
aday-3    0.548        8.77 px    11.68 px  0.751

hedef x-yuksekligi: 8.77 px (aday-3, 16px)
aday      esdeger nominal boyut   fark
aday-1                 18.27 px +2.27 px
aday-2                 16.86 px +0.86 px
aday-3                 16.00 px +0.00 px

aday      cikinti+inis (em)   esdeger boyutta (px)
aday-1               1.000                 18.27
aday-2               1.030                 17.37
aday-3               1.051                 16.82

Çıktının ikinci bloğu, “16 piksel” ifadesinin tek başına bir şey söylemediğini gösteriyor. Aynı görünen büyüklüğü tutturmak için aday-1’in 18.27 piksele çıkması gerekiyor; aradaki fark 2.27 piksel, yani taban boyutun yüzde on dördü. Bir yazı tipi değiştirildiğinde bütün boyut ölçeğinin yeniden ayarlanması gerekmesinin nedeni budur. Ölçek, bir sonraki dersin konusudur ve girdisi bu hesaptır.

Üçüncü blok ikinci bir sonucu veriyor. Çıkıntı ile inişin toplamı, satır kutusunun taban yüksekliğini belirler. Aday-3, eşdeğer büyüklükte daha küçük bir nominal boyutta çalıştığı için satır kutusu da daha kısa oluyor: 16.82 piksele karşı 18.27. Aynı satır aralığı oranıyla dizilmiş iki metin bloğundan biri, aynı görünen büyüklükte olmasına rağmen daha sıkı duracaktır.

Büyük harf yüksekliğine oranlanmış x-yüksekliği (x/buyuk harf sütunu) ikinci bir işaret verir. Bu oran yükseldikçe küçük harfler büyük harflere yaklaşır; büyük harfle başlayan sözcüklerin baştaki çıkıntısı zayıflar. Sözcük şeklinin taranmayı hızlandırdığı yerlerde — arama sonuçlarındaki kayıt başlıkları — bu, çok yüksek bir oranın bedelidir.

Karakterlerin Birbirinden Ayrılması

Seçilebilirliğin iki denetlenebilir yüzü vardır: gereken karakterlerin yazı tipinde bulunması ve bulunanların birbirine karışmaması. İkisi de arayüzde gerçekten geçen metin üzerinden sınanır, örnek bir cümle üzerinden değil.

// kapsam.mjs — katalog metinlerinin yazi tipi kapsamiyla ve ayirt edilebilirlikle denetimi

// Katalog arayuzunde gercekten gorunen alanlar.
const kayitlar = [
  { baslik: "Işık ve Gölge: Bir Optik Tarihi", yazar: "Öztürk, Şükran", yil: 1998, rafKodu: "QC353.I8", isbn: "9789750718533" },
  { baslik: "Çağdaş Türk Şiirinde İmge", yazar: "Ilgaz, İbrahim", yil: 2004, rafKodu: "PL248.C1", isbn: "9789944882101" },
  { baslik: "Ağ Protokolleri El Kitabı", yazar: "Gündoğdu, Elif", yil: 2011, rafKodu: "TK5105.5", isbn: "9786055829476" },
];

// 1) Kapsam denetimi: aday yazi tipinin bildirdigi kod noktasi araliklari.
const araliklar = {
  "yalniz-latin-temel": [[0x0020, 0x007e]],
  "latin-1-ekli": [[0x0020, 0x007e], [0x00a0, 0x00ff]],
  "latin-genisletilmis-a": [[0x0020, 0x007e], [0x00a0, 0x00ff], [0x0100, 0x017f], [0x2010, 0x2027]],
};

function kapsiyorMu(araliklar, kod) {
  return araliklar.some(([alt, ust]) => kod >= alt && kod <= ust);
}

const metin = kayitlar.map((k) => `${k.baslik} ${k.yazar} ${k.yil} ${k.rafKodu} ${k.isbn}`).join(" ");
const kullanilan = [...new Set([...metin])].sort((a, b) => a.codePointAt(0) - b.codePointAt(0));

console.log(`katalog metinlerinde gecen farkli karakter sayisi: ${kullanilan.length}`);
for (const [ad, ar] of Object.entries(araliklar)) {
  const eksik = kullanilan.filter((c) => !kapsiyorMu(ar, c.codePointAt(0)));
  const yazim = eksik
    .map((c) => `${c}(U+${c.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")})`)
    .join(" ");
  console.log(`${ad.padEnd(24)} eksik ${String(eksik.length).padStart(2)}: ${yazim || "-"}`);
}

// 2) Ayirt edilebilirlik: birbirine karisabilen karakter kumeleri.
const karisabilir = [
  ["I", "l", "1", "|"],
  ["0", "O", "o"],
  ["5", "S", "s"],
  ["8", "B"],
  ["I", "İ", "i", "ı"],
];

console.log("\nalan       karisabilir kume icinden birlikte gecenler");
const alanlar = [
  ["rafKodu", kayitlar.map((k) => k.rafKodu)],
  ["isbn", kayitlar.map((k) => String(k.isbn))],
  ["yazar", kayitlar.map((k) => k.yazar)],
];
for (const [alanAdi, degerler] of alanlar) {
  const harfler = new Set(degerler.join("").split(""));
  const catisan = karisabilir
    .map((kume) => kume.filter((c) => harfler.has(c)))
    .filter((v) => v.length >= 2)
    .map((v) => v.join("/"));
  console.log(`${alanAdi.padEnd(10)} ${catisan.length ? catisan.join("  ") : "-"}`);
}
katalog metinlerinde gecen farkli karakter sayisi: 54
yalniz-latin-temel       eksik  9: Ç(U+00C7) Ö(U+00D6) ö(U+00F6) ü(U+00FC) ğ(U+011F) İ(U+0130) ı(U+0131) Ş(U+015E) ş(U+015F)
latin-1-ekli             eksik  5: ğ(U+011F) İ(U+0130) ı(U+0131) Ş(U+015E) ş(U+015F)
latin-genisletilmis-a    eksik  0: -

alan       karisabilir kume icinden birlikte gecenler
rafKodu    I/1
isbn       -
yazar      I/l  I/İ/i

Birinci blok, kapsam sorununun neden gözle yakalanamadığını gösteriyor. Latin-1 ekli kapsam Türkçenin çoğu harfini karşılar; eksik kalan beş kod noktası tam olarak Latin Genişletilmiş-A bölgesindeki noktalı ve noktasız i çifti, ğ ve ş harfleridir. Bir yazı tipi, örnek metinde bu beş harf geçmediği sürece kusursuz görünür. Yedek aileye düşen harfler farklı bir x-yüksekliğiyle çizilir ve aynı sözcük içinde iki ayrı yazı tipi belirir. Kod noktaları M01/K01 Bilgisayarlar Nasıl Çalışır kursunda tanımlanmıştı; buradaki denetim onların doğrudan bir uygulamasıdır.

İkinci blok, hangi alanın hangi karışıklığı taşıdığını söylüyor. Raf kodu alanında I ile 1 birlikte geçiyor; bu alan bir kütüphanede sesli okunarak ya da elle not edilerek kullanılır, yani karışıklığın bedeli somuttur. ISBN alanı yalnız rakam taşıdığı için listedeki hiçbir kümeyle çakışmıyor. Yazar alanında ise Türkçeye özgü bir çakışma var: büyük I, küçük l ve noktalı İ aynı alanda bulunuyor.

Bu bulgunun iki ayrı çözümü vardır ve ikisi farklı yerlere dokunur. Raf kodu alanına eşit aralıklı aileyi vermek, harf ile rakamı iki farklı çizim geleneğine ayırır — bu bir yazı tipi kararıdır. Yazar alanındaki I ve İ karışıklığı ise yazı tipiyle çözülmez, çünkü ikisi de gerçekten gereken ayrı harflerdir; orada gereken şey, adayın büyük I harfini tabanlı ve kancalı biçimlerden hangisiyle çizdiğini denetlemektir.

Ailenin Taşıyabileceği Hiyerarşi Yükü

Görsel Hiyerarşi dersinde kritik ayrımların en az iki kanalda ifade edilmesi kural olarak konmuştu. Kanallardan biri ağırlıktı. Bir yazı tipi ailesinin sunduğu ağırlık sayısı, bu kuralın kaç yerde uygulanabileceğini doğrudan sınırlar.

Katalog arayüzü en az üç ağırlık düzeyi ister: kayıt başlığı için kalın, gövde için normal, bastırılmış üstveri için yine normal ama düşük kontrastlı. İki ağırlık sunan bir aile bunu karşılar. Tek ağırlık sunan bir aile karşılamaz; o durumda hiyerarşinin bütün yükü boyut ve kontrast kanallarına biner ve ilk derste hesaplanan “tek bacaklı ayrım” durumu üretilir.

Rakam biçimi ikinci bir kısıttır. Bir ailenin rakamları orantılı (proportional) ya da eşit genişlikli (tabular) çizilmiş olabilir. Orantılı rakamlarda 1 diğerlerinden dar durur; alt alta dizilmiş yayın yıllarında sütun kayar. Katalog sonuç listesi yılları bir sütunda hizalıyorsa eşit genişlikli rakam gerekir. Eşit aralıklı aile bunu zaten sağlar; tırnaksız ailede ise ayrıca bildirilmiş bir özellik olması gerekir.

Üçüncü kısıt, gerçek eğik biçimin bulunup bulunmadığıdır. Ailede eğik kesim yoksa tarayıcı harfleri yatırarak taklit üretir; bu taklit, harf uçlarını bozar ve küçük boyutlarda seçilebilirliği düşürür. Katalog arayüzünde eğik biçim yalnızca bir yerde gerekiyor — kayıt ayrıntısındaki kaynak künyesi — ve o tek yer bile ailenin seçimini kısıtlar.

Bu üç kısıt bir araya geldiğinde seçim ölçütü sadeleşir: aile, arayüzün istediği kanalları gerçekten sunuyor mu? Sunmuyorsa, eksik kanalın yükü başka kanallara aktarılır ve o kanallar zaten doludur.

Özet

  • Seçilebilirlik karakter düzeyinde, okunabilirlik blok düzeyinde ölçülür; birincisi yazı tipi değişikliğiyle, ikincisi düzen değişikliğiyle çözülür.
  • Yazı tipi sınıfları ürün adı vermeden karar vermeyi sağlar; her sınıf belirli bir işi ucuzlatır ve başka bir işi pahalılaştırır.
  • Nominal boyut görünen büyüklüğü vermez; görünen büyüklük x-yüksekliği oranından hesaplanır ve aynı ölçüyü tutturmak farklı ailelerde farklı nominal boyut gerektirir.
  • Abece kapsamı, arayüzde gerçekten geçen kod noktaları üzerinden denetlenir; eksik kapsam örnek metinde görünmez ama yedek aileye düşen harflerle kendini gösterir.
  • Karakter karışıklığı alan alan denetlenir; hangi karışabilir kümenin hangi alanda gerçekten bir arada geçtiği hesaplanabilir bir sorudur.
  • Ailenin sunduğu ağırlık sayısı, rakam genişliği ve gerçek eğik kesimi, hiyerarşinin kaç kanalda kurulabileceğini doğrudan sınırlar.

Sonraki Adım

Bu ders tek bir boyutu — gövde metninin taban boyutunu — sabitledi ve o boyutun ailelere göre değiştiğini gösterdi. Arayüzde ise tek boyut yoktur: sayfa başlığı, kayıt başlığı, yazar adı, üstveri ve düğme metni ayrı basamaklardadır. Bu basamaklar tek tek seçilirse sayı kalabalığı büyür ve ilk derste ölçülen ayrım eşikleri rastgele tutturulur ya da kaçırılır. Sonraki ders basamakları bir tabandan ve bir orandan türetir, üretilen ölçeği piksel ızgarasına yuvarlar ve komşu basamakların ayrım eşiğini gerçekten geçip geçmediğini hesaplar.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat