Font Loading Strategies
Font web yang besar bisa menunda text LCP sampai 1-2 detik. Strategi loading font yang benar menentukan apakah user melihat FOIT (text tidak terlihat) atau FOUT (text terlihat dengan font fallback dulu).
FOIT vs FOUT
- FOIT (Flash of Invisible Text) — browser sembunyikan text sampai custom font selesai download. Akibatnya halaman terlihat "kosong" meskipun HTML sudah siap. Buruk untuk LCP.
- FOUT (Flash of Unstyled Text) — browser render dengan fallback font dulu, lalu swap ke custom font ketika siap. User bisa baca lebih cepat, walau ada "flash" perubahan font.
Property font-display
Property ini mengontrol trade-off antara FOIT dan FOUT di @font-face:
| Value | Block Period | Swap Period | Kapan pakai |
|---|---|---|---|
auto | Browser default | Browser default | Jangan — tidak predictable |
block | ~3s | Infinite | Logo/branding yang wajib persis |
swap | 0s | Infinite | Default terbaik — body text |
fallback | 100ms | 3s | Font yang "nice to have" |
optional | 100ms | 0s | Font opsional, hanya kalau sudah cache |
@font-face {
font-family: "Inter";
src: url("/fonts/inter.woff2") format("woff2");
font-display: swap;
font-weight: 400;
unicode-range: U+0000-00FF; /* Latin saja */
}
Self-Host vs CDN
- Self-host — file font di origin yang sama dengan HTML. Tidak ada DNS/TLS handshake tambahan, bisa di-preload. Umumnya lebih cepat di 2024+.
- Google Fonts CDN — dulu dianggap lebih cepat karena shared cache, tapi sejak browser isolation (per-origin cache) tidak ada keuntungan itu lagi.
Preload Font Kritis
Untuk font yang dipakai di above-the-fold text, preload agar browser mulai download di awal (bukan menunggu CSS di-parse dulu):
<link rel="preload" href="/fonts/inter.woff2"
as="font" type="font/woff2" crossorigin>
Catatan: crossorigin wajib meski font self-hosted — font dianggap CORS resource. Tanpa crossorigin, browser akan download 2× (sekali preload, sekali untuk dipakai CSS).
Font Subsetting dengan unicode-range
File font mengandung glyph untuk ratusan bahasa. Dengan subsetting, browser hanya download chunk yang dibutuhkan:
@font-face {
font-family: "Inter";
src: url("/fonts/inter-latin.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153;
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter-cyrillic.woff2") format("woff2");
unicode-range: U+0400-045F;
}
Halaman Bahasa Indonesia hanya download Latin subset (~20KB), bukan full file (~200KB).
Variable Fonts
Satu file bisa menggantikan seluruh family (Regular, Bold, Italic, Light, dst). Contoh: Inter Variable ~110KB vs 6 static file ~330KB total. Sintaks sama tapi font-weight menerima angka bebas:
@font-face {
font-family: "Inter";
src: url("/fonts/inter-variable.woff2") format("woff2-variations");
font-weight: 100 900; /* range, bukan fixed */
font-display: swap;
}
h1 { font-weight: 750; /* nilai bebas */ }