Font display strategy

폰트 디스플레이 전략

A CSS property that decides how text behaves while a custom font is still downloading — hide it until ready (FOIT), or show it in a fallback font first (FOUT).

Also known as: FOITFOUTfont-display
···
html
<div class="stage">
  <div class="sample" id="sample">Loading Text</div>
  <div class="phase" id="phase">block · 0ms</div>
  <div class="note">시뮬레이션 — 실제 네트워크 요청 없음</div>
</div>
css
.stage{display:grid;justify-items:center;gap:10px}
.sample{font:800 8vmin/1.2 -apple-system,system-ui,sans-serif;color:var(--fg);transition:opacity .15s, font-style .15s}
.sample.hidden{opacity:0}
.sample.custom{font-style:italic;color:var(--accent)}
.phase{font:11px ui-monospace,Menlo,monospace;color:var(--accent-2)}
.note{font:10px ui-monospace,Menlo,monospace;color:var(--muted)}
js
const sample = document.getElementById('sample');
const phase = document.getElementById('phase');
const strategies = [
  { name: 'block', steps: [[0,'hidden'],[500,'hidden'],[900,'fallback-then-custom']] },
  { name: 'swap', steps: [[0,'fallback'],[700,'custom']] },
  { name: 'fallback', steps: [[0,'hidden'],[150,'fallback'],[900,'stays-fallback']] },
  { name: 'optional', steps: [[0,'hidden'],[100,'fallback-forever']] },
];
let s = 0;
function runStrategy(){
  const strat = strategies[s % strategies.length];
  strat.steps.forEach(function(step){
    setTimeout(function(){
      const [ms, state] = step;
      sample.classList.remove('hidden', 'custom');
      if (state === 'hidden') sample.classList.add('hidden');
      if (state === 'custom' || state === 'fallback-then-custom') sample.classList.add('custom');
      phase.textContent = 'font-display: ' + strat.name + ' · ' + ms + 'ms · ' + state;
    }, step[0]);
  });
  s++;
  setTimeout(runStrategy, 2600);
}
runStrategy();

A web font is a file, and files take time to download. What the browser shows in the meantime falls into two broad camps: FOIT (Flash of Invisible Text) hides text entirely until the font arrives, and FOUT (Flash of Unstyled Text) shows text immediately in a fallback font, then swaps to the custom font once it loads.

CSS `font-display` picks the strategy. `block` hides text briefly (typically ~3s), falls back if the font still hasn't arrived, and swaps in later when it does (closer to FOIT). `swap` shows the fallback immediately and swaps as soon as the font loads (FOUT). `fallback` hides only very briefly, then — once the swap window passes — sticks with the fallback permanently. `optional` gives up on the custom font entirely on a slow connection, using only the fallback — useful for avoiding layout shift once content has already settled.

This site loads no external fonts, so the demo simulates each strategy's timeline rather than a real font load — no actual network request happens, which the demo states plainly on screen. On slow connections (3G, low-end devices), `swap` improves perceived speed but can show a visible style "snap"; `optional` avoids that snap but risks never showing the custom font at all — a real trade-off, not a free win.

When to use

Use `swap` for body text that needs to be readable immediately; consider `optional` where layout shift must be avoided entirely. It's also common to just leave it at `auto`, the browser default.