Font subsetting

폰트 서브셋팅

Stripping a font file down to only the glyphs actually used, discarding the rest — especially effective for writing systems with large character counts, like Hangul.

Also known as: 글리프 서브셋Font subsetting
···
html
<div class="stage">
  <p class="sample" id="sample">타이포그래피는 읽기의 목소리를 디자인하는 일이다</p>
  <div class="readout" id="readout">계산 중…</div>
</div>
css
.stage{display:grid;justify-items:center;gap:14px;width:min(94%,420px)}
.sample{font-size:15px;line-height:1.6;color:var(--fg);margin:0;text-align:center;font-family:-apple-system,system-ui,"Apple SD Gothic Neo",sans-serif}
.readout{font:11px ui-monospace,Menlo,monospace;color:var(--muted);text-align:center;line-height:1.7}
.bar{width:220px;height:8px;border-radius:4px;background:var(--line);overflow:hidden}
.bar-fill{height:100%;background:var(--accent);width:0;transition:width 1.2s ease}
js
const sample = document.getElementById('sample');
const readout = document.getElementById('readout');
const FULL_HANGUL_COUNT = 11172;
const text = sample.textContent;
const unique = new Set([...text].filter(function(ch){ return ch.trim().length > 0; }));
const pct = (unique.size / FULL_HANGUL_COUNT * 100);
const bar = document.createElement('div');
bar.className = 'bar';
const fill = document.createElement('div');
fill.className = 'bar-fill';
bar.appendChild(fill);
readout.textContent = '';
readout.appendChild(document.createTextNode('이 문장의 고유 글자 ' + unique.size + '개 / 한글 완성형 11,172자 = 약 ' + pct.toFixed(3) + '%'));
readout.appendChild(document.createElement('br'));
readout.appendChild(bar);
requestAnimationFrame(function(){ fill.style.width = Math.max(pct * 18, 2) + '%'; });

Precomposed Hangul spans 11,172 characters; Hanzi runs into the tens of thousands. A font file holding outline data for all of them ends up dozens of times heavier than a Latin-only font — a full Korean font commonly weighs several megabytes. Yet a typical web page rarely uses more than a few hundred distinct characters.

Subsetting strips a font file down to just the character set actually needed, dropping the remaining glyphs and hinting data to shrink it drastically. Where the exact characters that will appear are fixed — a logo, a static headline — a tiny subset containing only those characters is possible; for body text, where the character set is unpredictable, a common middle ground keeps only the most frequently used characters (say, a high-frequency subset of the 2,350 commonly used precomposed Hangul syllables).

Dynamic subsetting — CSS `unicode-range`, where the browser only requests the Unicode ranges it actually needs — lets a server pre-split a font into chunks and serve only the chunks a given page requires. This site loads no external font files at all, so it can't produce a real subset; the demo instead computes, honestly, what percentage of a full character set a given sentence's unique characters would represent.

When to use

Almost always worth considering when serving a Korean web font — shipping the full precomposed set makes load times noticeably worse. Logos and fixed phrases are worth their own tiny dedicated subset.