If you have ever tried to use a real Chinese, Japanese, or Korean typeface on the web, you already know the problem: a single CJK font file can be 5–15 MB. A Latin font might be 30–80 KB. Ship the CJK file the naive way and your page weight explodes, your Largest Contentful Paint tanks, and visitors on mobile leave before the text even renders.

The good news is that CJK fonts are very solvable — you just cannot treat them like Latin fonts. Here is the approach that works in production.

Why CJK fonts are so large

A Latin font needs a few hundred glyphs. A usable Simplified Chinese font needs 7,000+ common characters, and a full-coverage one can contain 20,000–30,000 glyphs. File size scales with glyph count, so no amount of compression alone will make a full CJK font small. WOFF2 helps (typically 30–40% smaller than TTF), but a 10 MB TTF still becomes a 6–7 MB WOFF2. You have to reduce which glyphs each visitor downloads, not just compress the file.

1. Split by unicode-range

The single most effective technique is font slicing: split one large font into 50–100 small subset files, each covering a contiguous unicode-range, and declare them all under one font-family in CSS.

@font-face { font-family: 'My CJK'; src: url('/fonts/cjk-010.woff2') format('woff2'); unicode-range: U+4E00-4FFF; font-display: swap; } @font-face { font-family: 'My CJK'; src: url('/fonts/cjk-011.woff2') format('woff2'); unicode-range: U+5000-5FFF; font-display: swap; } 

The browser is smart here: it only downloads the slices that contain characters actually used on the current page. A typical article page might trigger 8–15 slices at 30–60 KB each instead of one 6 MB file. Tools like cn-font-split and Google Fonts' own text-subsetting pipeline automate the slicing.

2. Always pair with a strong system fallback stack

Never let CJK text block on a web font. Use font-display: swap and a fallback stack that looks decent on every platform:

body { font-family: 'My CJK', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC', sans-serif; } 

On most Chinese users' devices, PingFang (Apple) or Microsoft YaHei (Windows) will render instantly while the web font slices load in. If the web font never arrives, the page is still perfectly readable — this is progressive enhancement, not failure.

3. Subset for your actual content when you can

If large parts of your site are static — a landing page headline, a logo lockup, navigation labels — generate a tiny custom subset containing only those characters. A 200-character headline subset is often under 10 KB and can even be inlined as a data URI or preloaded. Reserve the full sliced font for user-generated or long-form content where you cannot predict the characters.

4. Preload sparingly, cache aggressively

Do not preload a whole CJK font. At most, preload the one or two slices covering your headline characters. For the rest, rely on long-lived caching: font files never change under a given URL, so serve them with Cache-Control: public, max-age=31536000, immutable and version the filename when you update the typeface. Repeat visits then cost almost zero font bytes.

5. Check the licence before you split or self-host

Not every free-to-download font is free to subset, modify, or self-host. Open licences like SIL Open Font License 1.1 generally allow subsetting and web embedding, but some freeware licences restrict redistribution of modified files — and a sliced font is a redistributed modified file. Before you ship, read the licence for modification and embedding clauses. If you are browsing downloadable Chinese fonts on a library like FontHubs, check each family's licence field first, and prefer OFL-licensed families for sliced self-hosting.

A quick checklist

  • Convert to WOFF2, then slice by unicode-range — compression alone is not enough
  • Use font-display: swap plus a native CJK fallback stack
  • Subset static headlines down to the exact characters used
  • Preload at most 1–2 slices; cache font files immutably for a year
  • Verify the licence allows subsetting and self-hosting

Done this way, a site can offer a distinctive CJK typeface at a real cost of a few hundred kilobytes per page — comparable to a hero image — instead of a multi-megabyte penalty. The typeface stops being a performance excuse and becomes a design choice you can actually afford.