One Variable Font Replaces Five Font Files
Resumo
Pixel shares a practical look at replacing five separate font files with one variable font. The announcement explains why trimming font weights only partly solves the problem, and how browsers download fonts based on what a page actually uses—helping improve loading performance without sacrificing typography.
DEV Community
I Was Shipping Five Font Files. One Variable Font Replaced Them All.
Open the network tab on a site with a half-decent type system and count the font requests. Four is normal. Six isn't rare. Every one of them is a separate .woff2 file for a separate weight — Regular, Medium, Semibold, Bold — sitting in the critical path before the browser can paint text in anything but a fallback font. Our design system had five: four weights plus a bold italic for pull-quotes. Nobody had decided that on purpose. It accumulated — a designer added Semibold for one component, Bold Italic followed for another, and eighteen months later the font folder looked like a weight had been added every time someone liked how it looked in Figma. The fix everyone reaches for first When this shows up in a performance audit, the fix is almost always the same: cut weights. Drop from five down to three. Merge Semibold into Medium. Ship Bold Italic as a font-style: oblique of regular Bold instead of a dedicated file. @font-face {
font-family: "Inter";
src: url("/fonts/inter-regular.woff2") format("woff2");
font-weight: 400;
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter-medium.woff2") format("woff2");
font-weight: 500;
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter-bold.woff2") format("woff2");
font-weight: 700;
}
This genuinely helps — three requests beat five. It also doesn't touch the actual shape of the problem: every weight you keep is still its own file, its own request, its own round trip. Cut too aggressively and you lose the weight your design actually needs; cut too little and you're back where you started with a slightly smaller number. Before you keep reading — guess how many of those weights the browser actually downloads on a page that only uses Regular body text and one Bold heading. The honest (and slightly surprising) answer is: two. Browsers don't fetch an @font-face file the moment it's declared — the CSS Fonts spec requires user agents to download only the faces a page's rendered text actually calls for, so Medium, Semibold, and Bold Italic never leave the server for this particular page. That's the one thing "cut weights" already gets right, mostly by accident. What it doesn't fix: those two downloads are still two separate round trips, and the moment any other page in the same design system reaches for a third weight — a Semibold stat callout, a Bold Italic pull-quote — that page pays for a third file, one request at a time, because nothing about a static setup can serve more than the single weight baked into each one. It's not about how many weights — it's about how many files Here's what the "cut weights" fix never addresses: a static font file is a fixed snapshot. One file draws letterforms at exactly 700 and nothing else. Want 650 for a hover state that should feel "almost bold but not quite"? You can't — 650 doesn't exist unless you shipped a sixth file for it. The weight scale looks continuous in your design tool and is actually a handful of hardcoded stops in production. A variable font isn't a set of snapshots. It's one file that encodes the whole range as interpolation data — the letterforms at 100 and the letterforms at 900, with the browser computing everything in between on the fly. Ask for font-weight: 538 and you get a real, rendered 538, not a browser fallback or a rounded guess. @font-face {
font-family: "Inter";
src: url("/fonts/inter-variable.woff2") format("woff2-variations");
font-weight: 100 900; / a range, not a single value /
font-stretch: 75% 125%;
}
That's the whole type system. One @font-face block. One network request. Every weight from thin to black, plus every stop in between, available from the same file: h1 { font-weight: 700; }
h2 { font-weight: 600; }
body { font-weight: 400; }
.btn:hover { font-weight: 538; } / yes, this is a valid value now /
Five requests become one. The five-weight design system from the top of this post could have shipped as a single file from day one — nobody needed to decide anything ab...

Powered by Readybot.io