Ders 08 / 19
Tipografi Belirteçleri
Metin düzeylerinin bileşik belirteç olarak tanımlanması, satır kutusunun aralık ızgarasına oturtulması, ızgara seçiminin çarpan sapmasıyla ödünleşimi ve düzeylerin ayrım eşiğiyle denetlenmesi.
İçindekiler
Renk belirteçleri bir bağımlılık gösterdi: bir rolün doğruluğu tek başına değil, üzerine düştüğü zeminle birlikte ölçülüyordu. Tipografide bağımlılık bir rolün içine taşınır.
Bir metin düzeyi tek bir sayı değildir. Kayıt başlığının boyutu 20 pikselse, satır yüksekliği, ağırlığı ve harf aralığı da o kararın parçasıdır. Bu dört alan ayrı belirteçlere dağıtılıp bileşenlerde tek tek birleştirildiğinde iki şey olur: yanlış birleşimler kurulabilir ve düzeyin tamamı hiçbir yerde görünmez. Bu ders tipografiyi bileşik belirteç olarak tanımlar ve ikinci bir kısıt ekler — satır kutusu, aralık ölçeğinin ızgarasına oturmak zorundadır.
Bileşik Belirteç ve Izgara Kısıtı
Bileşik belirteç (composite token), birden çok alanı tek bir ad altında toplayan
belirteçtir. kayit-basligi bir boyut değil, bir kayıttır: boyut basamağı, ağırlık, satır
kutusu ve harf aralığı.
Bileşik olmanın gerekçesi tutarlılık değil geçerliliktir. Satır Uzunluğu ve Aralığı dersinde satır aralığı çarpanının yazı tipinin çıkıntı ve iniş toplamının altına inemeyeceği gösterilmişti. Boyut ve çarpan ayrı belirteçler olduğunda bu koşul her birleşimde yeniden sınanmalıdır; bileşik belirteçte koşul bir kez sınanır ve kayda geçer.
İkinci kısıt aralık ölçeğinden gelir. Bir metin bloğunun kapladığı dikey ölçü satır kutusu yüksekliğidir; bir kartın toplam yüksekliği bu kutuların ve aralarındaki boşlukların toplamıdır. Aralık ölçeği 4 piksel tabanlı olduğu için satır kutuları 4’ün katı değilse toplamlar ızgaradan kayar. Kısıt şudur: satır kutusu, aralık ölçeğinin taban adımının katı olmalıdır. Bu, çarpanın serbest seçilemeyeceği anlamına gelir; çarpan hedeflenir, kutu yuvarlanır ve gerçek çarpan bu yuvarlamadan çıkar.
// tipografi.mjs — bilesik tipografi belirtecleri, satir kutusunun izgaraya oturtulmasi ve ayrim denetimi const TABAN = 16; // govde boyutu (px) const ORAN = 1.25; // Tipografik Olcek dersinde secilen oran const IZGARA = 4; // Aralik Olcegi dersindeki karma olcegin taban adimi (px) const CIKINTI_INIS = 1.051; // yazi tipinin bildirdigi cikinti+inis (em); alt sinir const HEDEF_CARPAN = 1.5; // govde metni icin secilen satir araligi carpani const ADIMLAR = [-1, 0, 1, 2, 3]; const boyut = (n) => Math.round(TABAN * Math.pow(ORAN, n)); console.log("adim boyut hedef kutu izgaraya oturan kutu gercek carpan sapma cikinti-inis"); const KUTU = {}; for (const n of ADIMLAR) { const b = boyut(n); const hedef = b * HEDEF_CARPAN; const kutu = Math.round(hedef / IZGARA) * IZGARA; const carpan = kutu / b; KUTU[n] = kutu; console.log( `${String(n).padStart(4)} ${String(b).padStart(6)} ${hedef.toFixed(2).padStart(11)} ` + `${String(kutu).padStart(21)} ${carpan.toFixed(4).padStart(14)} ${(carpan - HEDEF_CARPAN).toFixed(4).padStart(7)} ` + `${(carpan >= CIKINTI_INIS ? "gecti" : "KALDI").padStart(13)}` ); } // Izgara secimi bir odunlesimdir: kaba izgara toplamlari duzenler, carpan sapmasini buyutur. console.log("\nizgara en buyuk carpan sapmasi carpan araligi kart toplami izgaraya oturuyor mu"); for (const g of [1, 2, 4, 8]) { const carpanlar = ADIMLAR.map((n) => (Math.round((boyut(n) * HEDEF_CARPAN) / g) * g) / boyut(n)); const sapma = Math.max(...carpanlar.map((c) => Math.abs(c - HEDEF_CARPAN))); const kutu = Object.fromEntries(ADIMLAR.map((n) => [n, Math.round((boyut(n) * HEDEF_CARPAN) / g) * g])); const kartToplam = 16 + kutu[1] + 8 + 2 * kutu[0] + 8 + kutu[-1] + 16; console.log( `${String(g).padStart(6)} ${sapma.toFixed(4).padStart(22)} ${Math.min(...carpanlar).toFixed(3)} - ${Math.max(...carpanlar).toFixed(3)} ` + `${String(kartToplam).padStart(19)} ${(kartToplam % 4 === 0 ? "evet" : "HAYIR").padStart(21)}` ); } // Bilesik belirtecler: bir metin duzeyi tek bir sayi degil, dort alanli bir kayittir. // Harf araligi kurali: taban boyutta 0, her basamak yukarida -0.005em, her basamak asagida +0.005em. const harfAraligi = (n) => -0.005 * n; const BICEMLER = [ { ad: "sayfa-basligi", adim: 3, agirlik: 700, bolge: "sayfa" }, { ad: "bolum-basligi", adim: 2, agirlik: 700, bolge: "sayfa" }, { ad: "kayit-basligi", adim: 1, agirlik: 600, bolge: "kayit" }, { ad: "govde", adim: 0, agirlik: 400, bolge: "kayit" }, { ad: "govde-guclu", adim: 0, agirlik: 600, bolge: "kayit" }, { ad: "dugme-metni", adim: 0, agirlik: 600, bolge: "eylem" }, { ad: "ustveri", adim: -1, agirlik: 400, bolge: "kayit" }, { ad: "etiket", adim: -1, agirlik: 600, bolge: "kayit" }, ]; console.log("\nbicem boyut agirlik satir kutusu carpan harf araligi (em) harf araligi (px)"); for (const b of BICEMLER) { const px = boyut(b.adim); const em = harfAraligi(b.adim); console.log( `${b.ad.padEnd(16)} ${String(px).padStart(5)} ${String(b.agirlik).padStart(8)} ${String(KUTU[b.adim]).padStart(13)} ` + `${(KUTU[b.adim] / px).toFixed(3).padStart(7)} ${em.toFixed(3).padStart(18)} ${(em * px).toFixed(3).padStart(18)}` ); } // Ayrim denetimi: ayni bolgede birlikte gorunen bicemler ayirt edilebilmelidir. // Olcut, Gorsel Hiyerarsi dersindeki iki kanal kuralidir: boyut orani >= 1.15 ya da // agirlik farki >= 200. const BOYUT_ESIGI = 1.15; const AGIRLIK_ESIGI = 200; console.log("\nbolge bicem cifti boyut orani agirlik farki gecen kanal"); let zayif = 0; for (const bolge of [...new Set(BICEMLER.map((b) => b.bolge))]) { const grup = BICEMLER.filter((b) => b.bolge === bolge); for (let i = 0; i < grup.length; i++) { for (let j = i + 1; j < grup.length; j++) { const a = grup[i]; const b = grup[j]; const bo = Math.max(boyut(a.adim), boyut(b.adim)) / Math.min(boyut(a.adim), boyut(b.adim)); const af = Math.abs(a.agirlik - b.agirlik); const gecen = []; if (bo >= BOYUT_ESIGI) gecen.push("boyut"); if (af >= AGIRLIK_ESIGI) gecen.push("agirlik"); if (!gecen.length) zayif++; console.log( `${bolge.padEnd(7)} ${(a.ad + " / " + b.ad).padEnd(32)} ${bo.toFixed(3).padStart(11)} ` + `${String(af).padStart(14)} ${gecen.join("+") || "ZAYIF"}` ); } } } console.log(`ayrim uretmeyen cift: ${zayif}`); // Kayit kartinin dikey olcusu: satir kutulari ve aralik adimlari toplami izgaraya oturmali. const ARALIK = { "grup-ici": 8, "blok-arasi": 16, "bolum-arasi": 24 }; const KART = [ { tur: "aralik", ad: "blok-arasi" }, { tur: "bicem", ad: "kayit-basligi", satir: 1 }, { tur: "aralik", ad: "grup-ici" }, { tur: "bicem", ad: "govde", satir: 2 }, { tur: "aralik", ad: "grup-ici" }, { tur: "bicem", ad: "ustveri", satir: 1 }, { tur: "aralik", ad: "blok-arasi" }, ]; console.log("\nkayit karti dikey olcu"); let toplam = 0; for (const p of KART) { if (p.tur === "aralik") { toplam += ARALIK[p.ad]; console.log(` aralik ${p.ad.padEnd(16)} ${String(ARALIK[p.ad]).padStart(5)} px`); } else { const b = BICEMLER.find((x) => x.ad === p.ad); const y = KUTU[b.adim] * p.satir; toplam += y; console.log(` metin ${(p.ad + " x" + p.satir).padEnd(16)} ${String(y).padStart(5)} px (kutu ${KUTU[b.adim]})`); } } console.log(` toplam ${String(toplam).padStart(5)} px ${IZGARA} px izgarasina oturuyor mu: ${toplam % IZGARA === 0 ? "evet" : "HAYIR"}`); // Ayni kart, satir kutusu izgaraya oturtulmamis olsaydi ne olurdu? console.log("\nizgaraya oturtulmamis satir kutulariyla ayni kart"); let ham = 0; for (const p of KART) { if (p.tur === "aralik") ham += ARALIK[p.ad]; else { const b = BICEMLER.find((x) => x.ad === p.ad); ham += boyut(b.adim) * HEDEF_CARPAN * p.satir; } } console.log(` toplam ${ham.toFixed(1)} px izgaraya oturuyor mu: ${ham % IZGARA === 0 ? "evet" : "HAYIR"} fark: ${(toplam - ham).toFixed(1)} px`);
adim boyut hedef kutu izgaraya oturan kutu gercek carpan sapma cikinti-inis
-1 13 19.50 20 1.5385 0.0385 gecti
0 16 24.00 24 1.5000 0.0000 gecti
1 20 30.00 32 1.6000 0.1000 gecti
2 25 37.50 36 1.4400 -0.0600 gecti
3 31 46.50 48 1.5484 0.0484 gecti
izgara en buyuk carpan sapmasi carpan araligi kart toplami izgaraya oturuyor mu
1 0.0385 1.500 - 1.538 146 HAYIR
2 0.0385 1.484 - 1.538 146 HAYIR
4 0.1000 1.440 - 1.600 148 evet
8 0.2692 1.231 - 1.600 144 evet
bicem boyut agirlik satir kutusu carpan harf araligi (em) harf araligi (px)
sayfa-basligi 31 700 48 1.548 -0.015 -0.465
bolum-basligi 25 700 36 1.440 -0.010 -0.250
kayit-basligi 20 600 32 1.600 -0.005 -0.100
govde 16 400 24 1.500 0.000 0.000
govde-guclu 16 600 24 1.500 0.000 0.000
dugme-metni 16 600 24 1.500 0.000 0.000
ustveri 13 400 20 1.538 0.005 0.065
etiket 13 600 20 1.538 0.005 0.065
bolge bicem cifti boyut orani agirlik farki gecen kanal
sayfa sayfa-basligi / bolum-basligi 1.240 0 boyut
kayit kayit-basligi / govde 1.250 200 boyut+agirlik
kayit kayit-basligi / govde-guclu 1.250 0 boyut
kayit kayit-basligi / ustveri 1.538 200 boyut+agirlik
kayit kayit-basligi / etiket 1.538 0 boyut
kayit govde / govde-guclu 1.000 200 agirlik
kayit govde / ustveri 1.231 0 boyut
kayit govde / etiket 1.231 200 boyut+agirlik
kayit govde-guclu / ustveri 1.231 200 boyut+agirlik
kayit govde-guclu / etiket 1.231 0 boyut
kayit ustveri / etiket 1.000 200 agirlik
ayrim uretmeyen cift: 0
kayit karti dikey olcu
aralik blok-arasi 16 px
metin kayit-basligi x1 32 px (kutu 32)
aralik grup-ici 8 px
metin govde x2 48 px (kutu 24)
aralik grup-ici 8 px
metin ustveri x1 20 px (kutu 20)
aralik blok-arasi 16 px
toplam 148 px 4 px izgarasina oturuyor mu: evet
izgaraya oturtulmamis satir kutulariyla ayni kart
toplam 145.5 px izgaraya oturuyor mu: HAYIR fark: 2.5 px
Yuvarlama Çarpanı Dağıtıyor
Birinci tablo kısıtın bedelini gösteriyor. Hedef çarpan bütün basamaklarda 1.5; gerçekleşen çarpanlar 1.44 ile 1.60 arasında dağılıyor.
En büyük sapma birinci basamakta: 20 piksellik metnin hedef kutusu 30 piksel, 4’e yuvarlandığında 32 oluyor ve çarpan 1.60’a çıkıyor. İkinci basamakta yuvarlama aşağı gidiyor: 25 pikselin hedef kutusu 37.5, yuvarlanmış kutu 36, çarpan 1.44.
Sapmanın yönü keyfî değil, boyutun ızgaraya olan uzaklığına bağlıdır. Boyut ızgaranın katıysa — 16 ve 4’ün katı — hedef kutu da katı olur ve sapma sıfır kalır. Tipografik Ölçek dersinde yuvarlamanın komşu basamak oranını bozduğu gösterilmişti; burada aynı yuvarlama ikinci kez, bu kez satır aralığı üzerinde etkisini gösteriyor. Kaynak aynıdır: sürekli bir dizinin tam sayı ızgarasına oturtulması.
Son sütun bir güvence veriyor. Beş basamağın hiçbirinde çarpan, yazı tipinin dayattığı 1.051 alt sınırının altına inmiyor. Bu sınır aşılsaydı yuvarlama kabul edilemez olurdu; ızgara uyumu, satırların üst üste binmesini haklı çıkarmaz.
Izgara Seçimi Bir Ödünleşimdir
İkinci tablo kısıtın kendisini sorguluyor. Dört ızgara adayı, iki ölçütle karşılaştırılıyor: çarpan sapması ve kart toplamının ızgaraya oturması.
Bir ve iki piksellik ızgaralarda çarpan sapması küçük kalıyor (0.0385) ama kart toplamı 146 piksel çıkıyor ve 4 piksellik aralık ızgarasına oturmuyor. Bu, ince ızgaranın gerçek maliyetidir: satır kutuları düzgün görünür, ama bileşen yükseklikleri aralık ölçeğiyle uyuşmaz ve iki bileşen alt alta konduğunda hizalar kayar.
Sekiz piksellik ızgarada durum tersine dönüyor. Kart toplamı oturuyor (144) ama çarpan aralığı 1.231 ile 1.600 arasına açılıyor; sapma 0.2692. 1.231 çarpanı, aynı ölçeğin bir basamağında metnin belirgin biçimde sıkışması demektir. Kaba ızgara toplamları düzenler, tipografiyi bozar.
Dört piksel iki ölçütü birlikte karşılayan tek aday: sapma 0.10 ile sınırlı, kart toplamı 148 ile ızgaraya oturuyor. Seçimin gerekçesi estetik değil, iki kısıtın kesişimidir.
Harf Aralığı Boyuta Bağlı Bir Türevdir
Üçüncü tablo bileşik belirteçlerin tam hâlini veriyor. Harf aralığı sütunu, tek tek seçilmek yerine basamaktan türetiliyor: taban boyutta sıfır, her basamak yukarıda 0.005 em daha sıkı, her basamak aşağıda 0.005 em daha açık.
Kuralın gerekçesi optiktir. Aynı harf aralığı büyük boyutta daha geniş görünür, çünkü aralık boyutla birlikte büyür; küçük boyutta ise harfler birbirine yaklaşır ve seçilebilirlik düşer. Türetme bu iki eğilimi ters yönde dengeler.
Piksel sütunu türetmenin sonucunu somutlaştırıyor: sayfa başlığında −0.465 piksel, üstveride +0.065 piksel. Değerler em cinsinden yazıldığı için bu dönüşüm kendiliğinden olur ve boyut değiştiğinde yeniden hesaplanmaz. Bu, belirtecin em cinsinden tanımlanmasının gerekçesidir; piksel cinsinden yazılsaydı her basamak için ayrı bir değer tutulması gerekirdi.
Ayrım Denetimi Bölge İçinde Yapılır
Dördüncü tablo, Görsel Hiyerarşi dersindeki iki kanal kuralını biçem kümesine uyguluyor. On bir çiftin hepsi en az bir kanalda ayrılıyor; ayrım üretmeyen çift yok.
Denetimin bölge kısıtı burada belirleyicidir. Tipografik Ölçek dersinde komşuluk
denetiminin düzeyleri sıralı bir liste sandığı ve hiyerarşinin yalnız aynı anda görülen ögeler
arasında anlamlı olduğu belirtilmişti. Bu hesap o uyarıyı kurala çeviriyor: her biçemin bir
bölgesi var ve karşılaştırma yalnız aynı bölgedeki çiftler arasında yapılıyor. dugme-metni
eylem bölgesinde tek başına duruyor ve hiçbir çifte girmiyor; govde ile aynı boyut ve
ağırlıkta olması bir sorun değildir, çünkü ikisi aynı görsel alanda yarışmaz.
İki çift yalnız ağırlık kanalında ayrılıyor: govde ile govde-guclu, ustveri ile
etiket. Boyut oranları 1.000. Bu kabul edilebilir bir tasarımdır, ama bir koşul taşır:
ağırlık farkının gerçekten çizilebilmesi gerekir. Yazı Tipi Seçimi dersinde değişken yazı
tipinin ara ağırlıkları ürettiği gösterilmişti; sabit ağırlıklı bir aile kullanıldığında 600
ağırlığı yoksa tarayıcı 700’e yuvarlar ve etiket ile sayfa-basligi aynı ağırlığa düşer.
Tek kanala dayanan bir ayrım, o kanalın gerçekten var olmasına bağlıdır.
Toplamlar Izgarada Kapanıyor
Son iki blok kısıtın neden konduğunu kanıtlıyor. Kayıt kartı dört metin bloğu ve dört aralık adımından oluşuyor; ızgaraya oturtulmuş satır kutularıyla toplam 148 piksel, 4’ün katı.
Aynı kart, satır kutuları yuvarlanmamış hâlde 145.5 piksel. Yarım piksellik bir artık, tek bir kartta görünmez. Sonuç listesinde on kart alt alta dizildiğinde artık beş piksele çıkar ve kartların yanındaki süzgeç paneliyle hizalar kayar. Izgara Sistemleri dersinde yatay eksende gösterilen sorunun dikey eksendeki karşılığı budur: türetilmeyen bir ölçü, tekrar edildikçe biriken bir hata üretir.
Kartın toplam yüksekliği aynı zamanda bir yan çıktı sağlıyor: 148 piksel, Yoğunluk Kararları dersindeki ekran başına kayıt hesabının girdisidir. Tipografi belirteçleri ızgaraya oturtulduğunda bu hesap sabit kalır; oturtulmadığında her kart biraz farklı yükseklik alır ve hesap yaklaşık olur.
Yazılı Biçim
Bileşik belirteçler biçemde tek bir sınıf olarak yazılır; alanlar ayrı özel özelliklerden gelir ama birlikte uygulanır.
:root { --basamak--1: 13px; --basamak-0: 16px; --basamak-1: 20px; --kutu--1: 20px; --kutu-0: 24px; --kutu-1: 32px; } .bicem-kayit-basligi { font-size: var(--basamak-1); line-height: var(--kutu-1); font-weight: 600; letter-spacing: -0.005em; } .bicem-govde { font-size: var(--basamak-0); line-height: var(--kutu-0); font-weight: 400; letter-spacing: 0; }
Satır yüksekliğinin birimsiz çarpan yerine piksel olarak yazılması bilinçli bir karardır. Birimsiz çarpan kalıtılır ve alt ögelerde kendi boyutuyla yeniden çarpılır; piksel değer kalıtıldığında sabit kalır. Izgara kısıtı sabit kutu ister, dolayısıyla kutu piksel olarak bildirilir. Bunun bedeli, bir biçem sınıfının içinde farklı boyutta bir metin geçtiğinde kutunun ona uymamasıdır; sistem bunu bir kural olarak yasaklar — biçem sınıfları iç içe geçmez.
Bileşen katmanının burada nasıl kurulacağı da bir karardır. kayit-baslik-boyutu gibi bir
bileşen belirteci yalnız kayıt kartının yoğun ve seyrek sürümleri farklı basamak kullanıyorsa
açılır. Açılmadığı yerde bileşen doğrudan biçem sınıfını kullanır ve ayar noktası üretilmez.
Özet
- Bir metin düzeyi bileşik belirteçtir: boyut, ağırlık, satır kutusu ve harf aralığı tek bir ad altında tanımlanır, çünkü geçerlilik koşulları alanlar arasında kurulur.
- Satır kutusu aralık ölçeğinin taban adımının katı olmak zorundadır; çarpan hedeflenir, kutu yuvarlanır ve gerçek çarpan yuvarlamadan çıkar.
- Yuvarlama hedef çarpanı dağıtır (1.5 hedefiyle gerçekleşen çarpanlar 1.44–1.60 arasına yayılır) ve ızgara seçimi bu dağılımla toplamlar arasındaki ödünleşimdir: ince ızgara çarpanı korur ama bileşen toplamlarını kaydırır, kaba ızgara toplamları düzenler ama çarpan aralığını 0.27’ye açar.
- Harf aralığı basamaktan em cinsinden türetilir; em kullanımı boyut değiştiğinde yeniden hesap gerektirmez.
- Ayrım denetimi bölge içinde yapılır; yalnız ağırlık kanalında ayrılan çiftler, o ağırlığın yazı tipinde gerçekten bulunmasına bağımlıdır.
- Izgaraya oturtulmuş kutularla kartın toplam yüksekliği 148 piksel ve ızgaraya oturuyor; oturtulmamış hâlde 145.5 piksel çıkıyor ve artık, kart tekrarlandıkça birikiyor.
Sonraki Adım
Satır kutuları aralık ızgarasına oturtuldu, ama ızgaranın kendisi hâlâ piksel cinsinden tanımlı. Kullanıcının kök yazı boyutunu büyütmesi ya da tarayıcının ölçeği değiştirmesi durumunda piksel değerler sabit kalır ve metin büyürken boşluklar büyümez. Sonraki ders ölçü sistemini sayısallaştırır: aralık ve boyut belirteçlerini göreli birimlere çevirir, farklı kök boyutlarında tam sayı piksel üretip üretmediklerini denetler ve bileşen yüksekliklerini dokunma hedefi ölçütüyle sınar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.