Tarayıcı Performansı

Web Font Yüklemesi Nasıl Optimize Edilir?

Web font yükleme stratejilerini ve font-display davranışlarını gösteren teknik şema

Bir sayfa yüklenirken metinlerin bir süre görünmemesi ya da stilsiz halde belirmesi, kullanıcıya performans sorunlarından önce bir güvensizlik hissi verir. Bu durumun kaynağı çoğunlukla font yüklemesidir. Tarayıcı, özel bir yazı tipi gerektiren metni ekrana dökmeden önce o fontu indirmek zorundadır ve bu bekleme süresi birkaç parametreye göre dramatik biçimde değişebilir.

Web fontları görsel kimliğin vazgeçilmez parçası haline geldi. Ama bu yazı tiplerinin performans üzerindeki etkisi sıklıkla göz ardı edilir. Toplam font dosyası boyutu bazen sayfa görsellerini geçer; üçüncü taraf kaynaklardan gelen fontlar ekstra bağlantı gecikmeleri ekler. Küçük bir yapılandırma farkı, Core Web Vitals skorlarında belirgin değişikliklere yol açabilir.

Her seçeneğin farklı bir trade-off'u vardır. font-display değeri, preload stratejisi, self-hosting tercihi, subsetting — bunların her biri bağımsız bir etkiye sahiptir ve doğru kombinasyon sayfaya, içeriğe ve hedef kitleye göre değişir.

Görünmez metin ile stilsiz metin arasındaki ayrım

Tarayıcıların web fontuna yaklaşımında iki temel davranış vardır. İlki, font yüklenene kadar metni tamamen gizlemektir; buna FOIT (Flash of Invisible Text) denir. İkincisi, önce sistem fontuyla metni göstermek, font geldiğinde değiştirmektir; buna FOUT (Flash of Unstyled Text) denir.

İkisi de kullanıcıya farklı hissettirer. FOIT'te metin hazır olana kadar yoktur; kullanıcı bir süre boşluk görür. FOUT'ta metin gelir ama stili bir kez değişir; bu geçiş gözle fark edilebilir. Tarayıcılar varsayılan olarak genellikle 3 saniye süren bir blok periyodu uygular: bu süre içinde font gelmezse sistem fontuna geçiş yapar. CSS'teki font-display özelliği tam da bu periyotları kontrol eder.

font-display: swap nasıl çalışır

font-display: swap, FOUT yolunu açıkça tercih eder. Blok periyodu sıfıra indirilir: tarayıcı beklemez, hemen sistem fontunu gösterir. Font indirme tamamlandığında geçiş yapar.

Bu yaklaşım LCP üzerinde olumlu etki yaratır çünkü metin içerik hızla görünür hale gelir. Ancak geçiş anı CLS'e katkıda bulunabilir. Sistem fontu ile web fontu arasındaki metrik farkı büyükse — farklı karakter genişlikleri, farklı satır yükseklikleri — yerleşim kayar ve skor bozulur. swap değeri en yaygın tercih olmaya devam ediyor; "görünmez metin" neredeyse her zaman "stilsiz metin"den daha kötü bir deneyimdir, ama bunu körü körüne uygulamak CLS sorunlarını gizleyebilir.

FOUT neden her zaman sorun değildir

FOUT'un kötü bir şey olduğu varsayımı yaygındır ama koşulsuz doğru değildir. Sistem fontuyla gösterilen metin yine de okunabilir durumdadır; kullanıcı beklemez, içeriğe erişim hemen başlar. Ağ koşulları iyiyse geçiş 100–200 milisaniyede tamamlanır ve fark edilmez.

Sorun, geçişin yerleşimi bozduğu durumlarda başlar. Büyük başlıklar, dar kolonlar ya da sabit yükseklikte konteynerler içindeki metinler, iki fontin boyutsal farkı yüzünden geçiş anında sıçrar. Bu tam olarak CLS'in ölçtüğü etkidir. FOUT'u kabul etmek ama CLS'i kontrol altında tutmak çok daha sağlıklı bir hedeftir.

font-display: optional — sessiz ama güçlü seçenek

font-display: optional farklı bir strateji izler. Tarayıcıya yalnızca çok kısa bir pencere verilir (yaklaşık 100ms); bu sürede font gelmezse o sayfa yüklemesinde hiç kullanılmaz. Arka planda indirilmeye devam eder ve bir sonraki ziyarette cache'den anında gelir.

Bu değer CLS'i neredeyse tamamen ortadan kaldırır çünkü web fontu ya çok hızlı gelir (geçiş neredeyse görünmez olur) ya da o yüklemede hiç devreye girmez. LCP üzerindeki etkisi de iyidir çünkü bekleme yapılmaz. Dezavantajı tasarımsal: ilk ziyarette ziyaretçiler web fontunu görmeyebilir. Marka kimliği için fontun her koşulda görünmesi kritikse optional uygun olmayabilir. Ancak performans öncelikli projelerde bu seçenek haksız biçimde göz ardı edilir; optional + self-hosting + iyi önbellekleme kombinasyonu çoğu durumda en temiz sonucu verir.

Preload ile yükleme sırasını öne çekmek

Tarayıcı bir font dosyasını ancak o fontu kullanan CSS kuralını işledikten sonra keşfeder. CSS dosyası büyükse ya da geç indiriliyorsa fontun keşfi daha da ertelenir. Bu gecikme LCP'ye doğrudan yansır.

<link rel="preload" as="font" href="..." crossorigin> ile tarayıcıya bu font dosyasını diğer kaynakları beklemeden hemen indirmesi söylenir. Özellikle ilk ekranda görünen büyük başlıklar veya hero alanındaki metinler için anlamlı fark yaratır. Ama preload dikkatli kullanılmalıdır; preload edilmiş ama kullanılmayan bir kaynak boşa harcanmış bant genişliğidir. Resource hint mekanizmasının genel çalışması hakkında daha fazla bilgi bulunabilir.

Self-hosting: üçüncü taraf bağlantısından vazgeçmenin kazanımı

Google Fonts gibi hizmetler fonts.googleapis.com ve fonts.gstatic.com adreslerine bağlantı gerektirir. Her yeni origin, DNS çözümlemesi, TCP bağlantısı ve TLS el sıkışması demektir. Bu zincirleme gecikmeler zayıf ağlarda 100–300ms arasında olabilir.

<link rel="preconnect"> bu gecikmeyi azaltır ama tamamen ortadan kaldırmaz. Preconnect ve DNS prefetch mekanizmaları bu overhead'i minimize eder; ancak self-hosting — yani font dosyalarını kendi sunucunuzda barındırmak — bu bağlantı adımlarını tamamen ortadan kaldırır. Aynı origin üzerinden geldiği için DNS ve TLS yeniden kurulmaz. Pratik yükü vardır: dosyaları güncellemeniz ve cache politikasını yönetmeniz gerekir. Ama performans kazanımı bu yükü çoğunlukla karşılar.

Subsetting ile gereksiz karakterleri dışarıda bırakmak

Tam bir font dosyası onlarca karakter kümesini içerir: Latince harfler, Kiril, Yunanca, matematiksel semboller, özel karakterler. Türkçe içerik üreten bir site için bunların büyük çoğunluğuna gerek yoktur.

Subsetting, fontu yalnızca kullanılan karakterlerle sınırlandırır. Latin Extended-A kümesi Türkçe ihtiyacını büyük ölçüde karşılar. Tam bir Noto Sans dosyası megabaytlara ulaşabilirken doğru subset 20–30 KB'ın altında kalabilir. Google Fonts bu ayrımı URL parametreleriyle otomatik yapar. Self-hosting durumunda pyftsubset veya fonttools gibi araçlar kullanılır. Azalan dosya boyutu hem bant genişliği hem parse maliyeti açısından kazanım sağlar.

unicode-range ile koşullu yükleme

CSS'teki unicode-range tanımı, tarayıcıya bu font dosyasını yalnızca belirtilen karakter aralıklarından biri sayfada kullanılıyorsa indirmesini söyler. Örneğin Latin bloğu için bir dosya, Kiril bloğu için başka bir dosya tanımlanır; tarayıcı sayfanın içeriğine göre yalnızca gerekli olanı indirir.

Bu stratejinin avantajı, gereksiz ağ isteklerini baştan önlemesidir. Türkçe içerik sunan bir sitede Kiril karakteri yoksa o font dosyası hiç indirilmez. Google Fonts bu ayrımı halihazırda yapar; self-hosting durumunda @font-face bloklarında manuel olarak tanımlamak gerekir. Uygulaması biraz karmaşık görünse de sonuç nettir: gereksiz bayt transferi olmaz, parse maliyeti yalnızca kullanılan karakterlere düşer.

Variable font: tek dosyada çoklu ağırlık

Geleneksel yaklaşımda her font ağırlığı ayrı bir dosyadır. 400, 500, 600 ve 700 ağırlığı kullanan bir proje dört HTTP isteği ve dört ayrı parse işlemi demektir.

Variable font, bu ağırlıkları (ve bazen genişlik veya eğimi) tek bir dosyada barındırır. Dosya boyutu toplam geleneksel versiyondan küçük olmayabilir, ama HTTP istek sayısı düşer ve tarayıcı önbelleği tek bir varlığı yönetir. Modern tarayıcıların tamamı variable font'u destekler. Kullandığınız font ailesinin variable versiyonu mevcutsa ve birden fazla ağırlık kullanıyorsanız bu geçiş genellikle mantıklıdır. Google Fonts, variable font versiyonlarını wght ekseniyle sunar.

Font yüklemesinin LCP üzerindeki doğrudan etkisi

LCP büyük metin bloklarını da ölçer. Hero alanındaki büyük başlık web fontuyla render ediliyorsa ve o font geç geliyorsa LCP gecikir. Bu gecikme Lighthouse raporunda doğrudan görünür olmayabilir ama waterfall incelendiğinde font isteğinin LCP elementini ne kadar ertelediği anlaşılır.

Bunu kırmak için iki yol vardır. Birincisi, kritik fontu preload etmek — böylece tarayıcı HTML'i işlemeye başlar başlamaz font indirme de başlar. İkincisi, font-display: optional ile fallback fontu LCP için kullanmak — web font sessizce sonradan yüklenir ama LCP erken tamamlanır. Seçim, görsel kimlik önceliğine bağlıdır; ama her iki yaklaşım da bilinçli olarak uygulandığında geçerlidir.

Fallback font metriklerini eşleştirmek

FOUT sürecinde sistem fontundan web fontuna geçiş CLS üretir çünkü iki fontin boyutsal metrikleri — karakter genişliği, satır yüksekliği, taban çizgisi — genellikle farklıdır. Metin alanı boyut değiştirince sayfa sıçrar.

CSS size-adjust, ascent-override, descent-override ve line-gap-override özellikleri, fallback fontun metriklerini web fontunkiyle eşleştirmeye yarar. Bu tanımlar fallback için ayrı bir @font-face bloğunda kullanılır. Doğru değerleri bulmak deneme gerektirir; bazı araçlar (Fontaine, Next.js yerleşik font optimizasyonu) bu hesaplamayı otomatik yapar. Sonuç, geçiş anında neredeyse görünmez hale gelen bir font swap'tır: metin vardır, stilsizdir ama yerleşim kaymaz.

Yükleme stratejisini doğrulama yolları

Chrome DevTools Network sekmesinde font istekleri filtrelenerek dosya boyutu, başlatılma zamanı ve bitiş zamanı görülür. Preload çalışıyorsa font isteğinin diğerlerinden önce başlaması gerekir; waterfall görünümü bu sıralamayı net biçimde gösterir.

Lighthouse raporu, "Ensure text remains visible during webfont load" uyarısını font-display kullanılmayan durumlarda tetikler. CLS skoru bölümünde layout shift kaynakları listelenir; font kaynaklı kaymalar burada görünür. Gerçek kullanıcı verisi için Chrome UX Report veya alan ölçüm araçları, yapılan optimizasyonların gerçek trafiğe nasıl yansıdığını gösterir.

CLS ile font ilişkisi neden sık gözden kaçar

CLS kaynaklarını incelerken görsel kaymalar genellikle reklam alanları veya geç yüklenen görsellere bağlanır. Ama font kaynaklı kaymalar sıklıkla aynı kategoride değerlendirilmez çünkü gözle farkedilmesi daha güçtür; geçiş hızlıdır ve "doğal" hissettirer.

DevTools Performance sekmesinde Layout Shift kayıtları incelendiğinde hangi elemanın kaymaya neden olduğu görülür. Büyük başlıkların ya da hero alanındaki metin bloklarının shift kaynağı olarak çıkması, font geçişine işaret eder. Bu noktada fallback metrik eşleştirmesi veya font-display: optional stratejisi devreye alınabilir.

Font optimizasyonu, her değişikliğin tek bir metriği değil birkaçını aynı anda etkilediği bir alandır. font-display: swap LCP'yi iyileştirebilir ama CLS'i kötüleştirebilir. Preload ilk yükü hızlandırabilir ama yanlış uygulandığında gereksiz kaynak bloke eder. Bu kararları genel önerilerden değil, ölçümden hareketle vermek daha sağlıklı sonuç verir.

Self-hosting, subsetting ve variable font kombinasyonu çoğu proje için iyi bir başlangıç noktasıdır. Üçüncü taraf bağlantısı kalkar, gereksiz karakterler yüklenmez, istek sayısı düşer. Üstüne eklenen fallback metrik eşleştirmesi CLS'i kontrol altında tutar. Bu dört adım birlikte uygulandığında font kaynaklı performans sorunlarının büyük kısmı çözülür.

Daha ince ayar gerektiğinde unicode-range ile koşullu yükleme ve font-display: optional ile cache-first strateji devreye girer. Önbellek ısındıktan sonra ikinci ziyarette fark neredeyse sıfıra iner. Fontların her zaman görünmesi zorunlu değilse optional, beklenmedik kadar iyi çalışır.