typography

Unicode Range

Unicode range is the CSS sniper inside your @font-face blocks. You feed it comma separated lists of code points like U+0000-00FF or U+0100-024F and the browser treats the font file as a lazy loaded resource instead of a mandatory payload. It pairs perfectly with variable fonts because one axis rich file can split into a lean Latin base and targeted extension files. The browser parses your HTML scans for matching characters and fetches the right subset only when it sees a French accent an em dash or a mathematical operator. This turns the classic variable font bloat problem into a non issue. One network request for English marketing pages. A second only for the German legal page that actually needs those extra glyphs. The syntax lives right next to font-weight and font-display so it travels with the rest of your font stack decisions.

Unicode range is not subsetting. Subsetting is the build time meat grinder you run with pyftsubset that deletes unused glyphs from the WOFF2 itself. Unicode range is the loading instruction manual the browser reads after that step. It is not a magic fallback system either. Drop the ranges and you will see tofu boxes on a Russian site even if your variable font technically contains the Cyrillic. It is not something you guess at or copy from Stack Overflow. One wrong range and you ship 400 kilobytes of unused Greek symbols to every visitor while simultaneously breaking character rendering on your French checkout flow. It is also not a replacement for proper font-display swap or metric matched fallbacks. Those three tools solve different problems and all three must travel together or your Lighthouse scores stay red.

Look at the exact pattern copied from the variable fonts article and used by Vercel on their marketing site. They ship Geist variable with two @font-face rules. The first covers basic Latin with unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD. The second file carries Latin Extended with unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF. The Latin file stays under 180KB after subsetting. The extended file sits at 90KB and only loads for pages with characters like the c-cedilla in Francois or the o-umlaut in Dusseldorf. GitHub runs the same playbook for Mona Sans. Their primary UI font uses a tight Latin range plus a separate Cyrillic range that activates only on their Russian documentation. Stripe Press does this for their editorial variable font so a long essay about cryptography pulls in mathematical operators without forcing every reader to download the full glyph set. Linear uses it with Inter variable to keep their dense product UI under 140KB total while still supporting the occasional German or Spanish translation without layout shift.

The New York Times applies unicode-range to their custom variable serif so US readers never download the extra Greek and Cyrillic cuts needed for their international editions. Apple Music does the same with San Francisco variable splitting optical size and weight data across targeted language files so the app loads fast on Japanese iPhones without punishing English listeners. These teams all run pyftsubset first with the exact matching unicode values then attach the ranges in CSS. The result is variable fonts that feel infinite in design possibility but stay ruthlessly small in delivery. Google Fonts has shipped this pattern at planet scale since the early 2010s and every production team serious about typography copied the homework.

Use unicode range when you ship any variable font that supports more than basic English or when your audience crosses language boundaries even occasionally. Use it on editorial sites like Stripe Press where one article might need symbols the next does not. Use it with font-preload on the Latin base only and font-display swap on every block. Use it after you have run pyftsubset and verified the output files with real content from your site. Never use it alone. It demands the full production stack: subsetting first axis range trimming second preload third metric matched fallbacks fourth. Skip unicode range on a pure English SaaS dashboard that never leaves the basic Latin set. You will add build complexity for zero byte savings. Skip it when you are still prototyping and the design has not settled on final languages. Skip it if your ranges overlap across multiple files because the browser picks the first match and your carefully optimized variable font suddenly delivers the wrong weight axis on certain characters. Do not use it as theater. If your marketing site only ever serves English then one well subsetted variable font with no extra ranges wins every time.

Unicode range turns your variable font strategy from guesswork into a surgical system that ships exactly the bytes each visitor actually needs.

Related terms

Keep exploring