İçeriğe geç
academia.sh

Ders 20 / 26

Yazı Tipi Yükleme

Yazı tipi dosyasının belgeye bağlanması, alt küme aralıklarıyla koşullu indirme ve yükleme süresince görüntüleme davranışının seçilmesi.

İçindekiler

Önceki ders yazı tipini bir adla çağırdı: font-family: "Inter", system-ui, sans-serif. Adın karşılığı olan dosyanın nereden geldiği sorulmadı. Sistemde kurulu olmayan bir yazı tipi belgeye nasıl bağlanır ve dosya inerken metin ne olur?

Bu ders yazı tipi yüklemesini ele alır. Konu tipografiden çok yükleme sırasına ilişkindir ve Web’in Temelleri ve HTML kursundaki kaynak yükleme sırası dersinin bir uzantısıdır: yazı tipi de bir alt kaynaktır ve ne zaman geldiği sayfanın okunmasını etkiler.

Yazı Tipi Tanımı

@font-face kuralı bir aile adını bir dosyaya bağlar. Bir kural değildir — seçicisi yoktur, hiçbir ögeye uygulanmaz. Yaptığı iş, font-family listelerinde kullanılabilecek bir ad tanımlamaktır.

@font-face {
  font-family: "Istasyon Sans";
  src: url("/yazi/istasyon-sans.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

font-weight ve font-style burada bir bildirim değil, bir tanımdır: bu dosyanın hangi ağırlığı ve stili sağladığını söyler. Aynı aile adına farklı ağırlıklar için ayrı @font-face blokları yazılır ve tarayıcı, font-weight: 700 istendiğinde o ağırlığı sağlayan dosyayı seçer.

Bir ağırlık için dosya bildirilmediğinde tarayıcı en yakınını kullanır ve gerekirse hesapla kalınlaştırır. Önceki derste anılan bu davranış, @font-face bloklarının eksik yazıldığında ortaya çıkar.

src birden çok kaynak alabilir; ilk çözülebilen kullanılır. format() bildirimi, dosya indirilmeden biçimin tanınıp tanınmadığının anlaşılmasını sağlar — tanınmayan biçimdeki kaynak atlanır, indirilmez.

Alt Küme Aralıkları Koşullu İndirme Sağlar

unicode-range tanımı, bir dosyanın hangi kod noktalarını sağladığını bildirir. Bunun sonucu belirleyicidir: belgede o aralıktan hiç karakter yoksa dosya indirilmez.

Aşağıdaki program dört alt küme dosyası tanımlar ve üç metin için hangilerinin indirileceğini hesaplar.

// yazitipi.mjs — unicode-range ile alt kume secimi ve font-display zaman cizelgesi
const dilimler = [
  { ad: "latin.woff2",     araliklar: [[0x0000, 0x00ff], [0x0131, 0x0131], [0x2000, 0x206f]] },
  { ad: "latin-ext.woff2", araliklar: [[0x0100, 0x024f], [0x1e00, 0x1eff]] },
  { ad: "greek.woff2",     araliklar: [[0x0370, 0x03ff]] },
  { ad: "cyrillic.woff2",  araliklar: [[0x0400, 0x04ff]] },
];

function gerekenDilimler(metin) {
  const gerekli = new Map();
  for (const ch of metin) {
    const kod = ch.codePointAt(0);
    for (const d of dilimler) {
      if (d.araliklar.some(([a, b]) => kod >= a && kod <= b)) {
        if (!gerekli.has(d.ad)) gerekli.set(d.ad, new Set());
        gerekli.get(d.ad).add(ch);
        break;
      }
    }
  }
  return gerekli;
}

const metinler = [
  "Kuzey Yamac Olcum Istasyonu",
  "Kuzey Yamaç Ölçüm İstasyonu",
  "Sıcaklık: -3,4 °C — bağıl nem %78",
];

for (const m of metinler) {
  const g = gerekenDilimler(m);
  console.log(`metin: ${m}`);
  for (const [ad, karakterler] of g) {
    console.log(`  ${ad.padEnd(17)} indirilir  (${karakterler.size} ayri karakter)`);
  }
  const inmeyen = dilimler.filter((d) => !g.has(d.ad)).map((d) => d.ad);
  console.log(`  indirilmeyen: ${inmeyen.join(", ") || "(yok)"}`);
  console.log("");
}

console.log("--- font-display: engelleme ve degistirme sureleri ---");
const DAVRANIS = {
  "auto":     { engelleme: "gerceklestirime bagli", degistirme: "gerceklestirime bagli" },
  "block":    { engelleme: "kisa (~3s)",            degistirme: "sonsuz" },
  "swap":     { engelleme: "cok kisa (~100ms)",     degistirme: "sonsuz" },
  "fallback": { engelleme: "cok kisa (~100ms)",     degistirme: "kisa (~3s)" },
  "optional": { engelleme: "cok kisa (~100ms)",     degistirme: "yok" },
};
for (const [ad, d] of Object.entries(DAVRANIS)) {
  console.log(`${ad.padEnd(9)} engelleme=${d.engelleme.padEnd(22)} degistirme=${d.degistirme}`);
}

console.log("\n--- engelleme suresinde metin gorunur mu ---");
for (const [ad] of Object.entries(DAVRANIS)) {
  const gorunur = ad === "block" || ad === "auto" ? "hayir (gorunmez metin)" : "evet (yedek yazi tipi)";
  console.log(`${ad.padEnd(9)} -> ${gorunur}`);
}
metin: Kuzey Yamac Olcum Istasyonu
  latin.woff2       indirilir  (17 ayri karakter)
  indirilmeyen: latin-ext.woff2, greek.woff2, cyrillic.woff2

metin: Kuzey Yamaç Ölçüm İstasyonu
  latin.woff2       indirilir  (17 ayri karakter)
  latin-ext.woff2   indirilir  (1 ayri karakter)
  indirilmeyen: greek.woff2, cyrillic.woff2

metin: Sıcaklık: -3,4 °C — bağıl nem %78
  latin.woff2       indirilir  (22 ayri karakter)
  latin-ext.woff2   indirilir  (1 ayri karakter)
  indirilmeyen: greek.woff2, cyrillic.woff2

--- font-display: engelleme ve degistirme sureleri ---
auto      engelleme=gerceklestirime bagli  degistirme=gerceklestirime bagli
block     engelleme=kisa (~3s)             degistirme=sonsuz
swap      engelleme=cok kisa (~100ms)      degistirme=sonsuz
fallback  engelleme=cok kisa (~100ms)      degistirme=kisa (~3s)
optional  engelleme=cok kisa (~100ms)      degistirme=yok

--- engelleme suresinde metin gorunur mu ---
auto      -> hayir (gorunmez metin)
block     -> hayir (gorunmez metin)
swap      -> evet (yedek yazi tipi)
fallback  -> evet (yedek yazi tipi)
optional  -> evet (yedek yazi tipi)

İlk metin yalnızca ASCII karakterler taşıyor ve tek bir dosya indiriliyor. İkinci metin Türkçe yazılışıyla ve bir dosya daha ekleniyor — üstelik tek bir karakter yüzünden.

O karakter büyük noktalı İ’dir (U+0130) ve genişletilmiş Latin dilimine düşer. Küçük noktasız ı (U+0131) ise temel dilimin içinde tanımlıdır. İki harf, aynı alfabenin parçası olmalarına karşın iki ayrı dosyadan gelir. Üçüncü metinde aynı durum ğ (U+011F) için oluşuyor.

Bu, Türkçe metinlerde iki dosyanın birden indirileceği anlamına gelir; bir başlık yalnızca İ harfi taşıdığı için ikinci dosyayı bekler. Alt küme dilimleri kendi metnine göre üretildiğinde bu maliyet ortadan kalkar.

unicode-range kod noktalarıyla çalışır ve Bilgisayarlar Nasıl Çalışır kursunda tanımlanan karakter kümesi–kod noktası ayrımı burada doğrudan işler: aralıklar karakterlerin görünüşüne göre değil, kod noktası numaralarına göre bölünmüştür.

Görüntüleme Davranışı

Yazı tipi dosyası inerken metnin ne olacağı font-display ile seçilir. Karar iki süreyle tanımlanır:

Engelleme süresi (block period) — dosya beklenirken metin çizilmez. Bu sürede metin görünmezdir.

Değiştirme süresi (swap period) — metin yedek yazı tipiyle çizilir; dosya bu süre içinde gelirse yazı tipi değiştirilir.

Çıktının ikinci ve üçüncü blokları beş değeri bu iki süreye göre ayırıyor. Süre değerleri belirtimde öneri olarak verilir; kesin sayılar gerçekleştirime bağlıdır.

block — uzun bir engelleme süresi tanır. Sonuç, metnin bir süre görünmemesidir. Simge yazı tipleri gibi yedeği anlamsız olan durumlar dışında istenmeyen bir davranıştır.

swap — engelleme süresi çok kısadır; metin hemen yedek yazı tipiyle görünür ve dosya geldiğinde değişir. Metin hiçbir zaman görünmez olmaz, ama değişim anında düzen kayar.

fallback — kısa bir engelleme ve kısa bir değiştirme süresi tanır. Dosya geç gelirse yedek yazı tipi kalıcı olur ve düzen bir daha kaymaz.

optional — değiştirme süresi yoktur. Dosya çok hızlı gelmezse o sayfa yüklemesinde hiç kullanılmaz; önbelleğe alınıp sonraki ziyarette kullanılır.

Seçim bir ödünleşimdir: swap metnin okunabilirliğini önceler ve düzen kaymasını kabul eder; optional düzen kararlılığını önceler ve tasarlanan yazı tipinden vazgeçmeyi kabul eder.

Düzen Kaymasını Azaltmak

Yedek yazı tipi ile asıl yazı tipinin ölçüleri farklıysa, değişim anında metin kutusu büyür ya da küçülür ve altındaki her şey kayar. Bu kayma iki yolla azaltılır.

Birincisi, yedek yazı tipini ölçü olarak asıl yazı tipine yaklaştırmaktır. size-adjust, ascent-override, descent-override ve line-gap-override tanımları, yerel bir yazı tipinden yedek olarak kullanılacak bir aile üretmeyi sağlar:

@font-face {
  font-family: "Istasyon Sans Yedek";
  src: local("Arial");
  size-adjust: 97%;
  ascent-override: 90%;
}

İkincisi, dosyanın belge ayrıştırılırken erken istenmesini sağlamaktır:

<link rel="preload" href="/yazi/istasyon-sans.woff2" as="font" type="font/woff2" crossorigin>

Bu bağlantı bir biçem bağlantısı değildir; yalnızca kaynağın erken istenmesini bildirir. Yazı tipi istekleri, kaynak aynı kökten gelse bile çapraz köken kurallarına tabidir; bu yüzden crossorigin yazılmalıdır, yoksa kaynak iki kez indirilir.

Yerel Barındırma

Yazı tipi dosyasını kendi sunucusundan sunmak ile üçüncü taraf bir sunucudan çağırmak arasındaki fark bir başarım ayrıntısı değildir.

Üçüncü taraf bir kaynak, ayrı bir bağlantı kurulmasını gerektirir: ad çözümlemesi, bağlantı kurulumu ve güvenli el sıkışma yeniden yapılır. İnternet Nasıl Çalışır kursunda tanımlanan bu adımların her biri gecikme ekler.

İkinci bir sonuç gizlilikle ilgilidir: her istek, ziyaretçinin adresini ve hangi sayfayı görüntülediğini üçüncü tarafa bildirir. Yerel barındırma bu bildirimi ortadan kaldırır.

/* istasyon.css — 19. adım: yazı tipi tanımı */
@font-face {
  font-family: "Istasyon Sans";
  src: url("/yazi/istasyon-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+2000-206F;
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Istasyon Sans";
  src: url("/yazi/istasyon-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-024F, U+1E00-1EFF;
  font-weight: 400;
  font-display: swap;
}

body { font-family: "Istasyon Sans", system-ui, sans-serif; }

İki tanım aynı aile adını paylaşır ve aralıklarıyla ayrılır. Sayfada Türkçe metin bulunduğu için ikisi de indirilir; İngilizce bir sürümde yalnızca birincisi inerdi.

Özet

  • @font-face bir kural değil bir tanımdır: bir aile adını bir dosyaya bağlar ve o dosyanın hangi ağırlık ile stili sağladığını bildirir.
  • unicode-range dosyanın kapsadığı kod noktalarını bildirir; belgede o aralıktan karakter yoksa dosya hiç indirilmez.
  • Türkçe metinlerde büyük noktalı İ ve ğ gibi harfler genişletilmiş Latin dilimine düşer; tek bir karakter ikinci bir dosyanın indirilmesine yol açabilir.
  • font-display iki süreyi ayarlar: engelleme süresinde metin çizilmez, değiştirme süresinde yedek yazı tipiyle çizilir ve dosya gelirse değiştirilir.
  • Yerel barındırma ayrı bir bağlantı kurulumunu ortadan kaldırır ve ziyaretçi bilgisinin üçüncü tarafa bildirilmesini engeller.

Sonraki Adım

Yazı tipi geldi ve boyut ölçeği kuruldu. Metnin kendisi üzerinde yapılacak kararlar kaldı: satırların nasıl hizalanacağı, boşlukların nasıl işleneceği, harflerin büyük–küçük dönüşümü ve altı çizili metnin nasıl biçimlendirileceği. Sonraki ders bu kararları ele alır ve boşluk işlemenin kurallarını çalıştırılabilir bir örnekle gösterir.

İ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