How to variable weight presets vs multiple static font files
- Step 1Count the distinct weights your design actually uses — List every `font-weight` your UI renders. Two (Regular + Bold) leans static; four or more (Light, Regular, Medium, Bold, Black) leans variable. This count is the single biggest factor in the decision.
- Step 2Measure the real file sizes — Compare your variable WOFF2's size against the sum of the static WOFF2 weights you'd otherwise ship. The builder can't do this for you — it never reads fonts. Check sizes on disk or with an analysis tool.
- Step 3If variable wins, host the variable WOFF2 — Self-host the variable file and note its URL. If static wins instead, stop here and bake the static weights you need with [variable-font-freezer](/font-tools/variable-font-freezer).
- Step 4Generate the weight presets — Enter family name and the variable file's URL. The builder emits nine `@font-face` blocks (Thin 100 → Black 900), one cached file, each binding `font-weight` to `font-variation-settings: "wght"`.
- Step 5Prune to the weights you ship — Delete the generated blocks for weights your design doesn't use — fewer rules, same single file. The point of variable was never to use all nine; it's that the unused ones cost nothing extra on the wire.
- Step 6Preload the critical weight and verify — Add a `<link rel="preload">` for the variable file and confirm above-the-fold text renders in the right weight. Re-check your performance numbers against the static baseline you measured in step 2.
Variable presets vs static weight files
The structural trade-offs. Exact bytes depend on your fonts — this tool generates the variable-path CSS but does not measure files, so verify sizes yourself.
| Dimension | Variable + presets (this tool) | Multiple static WOFF2 |
|---|---|---|
| Downloads | 1 file, cached once | 1 per weight used |
| Single-file size | Larger (carries all weights) | Smaller per file |
| Total bytes at 4 weights | Usually less | Usually more |
| Total bytes at 1–2 weights | Often more | Often less |
| Cache granularity | Whole font cached together | Per-weight, independent |
| Extra weights later | Free (already in file) | New file + new request |
| Toolchain to produce | None (CSS only) | Instancing per weight |
Rough decision by weight count
Guidance, not a guarantee — always confirm against your real file sizes.
| Distinct weights used | Typically better | Why |
|---|---|---|
| 1 | Static (or freeze) | No reason to ship the whole axis for one weight |
| 2 | Often static | Two small files can beat one big variable file |
| 3 | Break-even | Measure both — close call |
| 4+ | Variable + presets | One cached file beats 4+ requests and total bytes |
| Many / unknown | Variable + presets | Future weights are free; no new requests |
What this tool does in the variable scenario
It produces the @font-face glue when you've decided variable wins. It does not measure, freeze, or shrink.
| Need | This tool | If not this tool |
|---|---|---|
| @font-face for the variable file | Yes — 9 presets | — |
| Decide variable vs static | No (guidance only) | Measure your files |
| Bake a static weight (static wins) | No | variable-font-freezer |
| Preload the critical weight | No | Add <link rel=preload> by hand |
Cookbook
Decision-driven recipes: when variable wins, here's the CSS; when static wins, here's where to go instead.
Variable wins (4 weights) — generate and prune
ExampleGenerate all nine, then keep only the four you use. Same single file backs them.
/* Generated, then pruned to Light/Regular/Bold/Black */
@font-face { font-family:"Inter"; font-weight:300;
font-variation-settings:"wght" 300;
src:url("/fonts/inter.var.woff2") format("woff2-variations"),
url("/fonts/inter.var.woff2") format("woff2");
font-style:normal; font-display:swap; }
/* + 400, 700, 900 blocks (identical shape) */Static wins (1 weight) — don't use this tool
ExampleFor a single weight, ship a static file instead — bake it from the variable font.
# Static path (1 weight): freeze instead of presets # → variable-font-freezer produces a static TTF at the chosen weight, # then convert to WOFF2 and ship one small file.
The caching argument, made concrete
ExampleWhy one variable file can beat several static across a multi-page visit.
Visit page A (uses 400, 700) then page B (adds 300, 900):
Static: page A fetches 2 files; page B fetches 2 MORE.
Variable: page A fetches 1 file; page B reuses the SAME cached file
for 300 and 900 — zero extra font bytes.Preload only when variable is the chosen path
ExampleThe builder writes @font-face; add the preload for the variable file yourself.
<link rel="preload" href="/fonts/inter.var.woff2"
as="font" type="font/woff2" crossorigin>Measuring the break-even on your own files
ExampleThe tool won't size anything — compare on disk before committing.
# Compare totals (illustrative — use YOUR numbers): variable: inter.var.woff2 = X KB (one file) static x4: Light+Regular+Bold+Black = sum of four WOFF2 # If the four-file sum > X, variable wins on bytes too.
Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
You ship only one or two weights
Variable may loseFor a single weight, a static file (or a frozen instance) is almost always smaller than the whole variable font — use variable-font-freezer instead of presets. For two weights it's a genuine measure-both situation; the variable file's fixed overhead may not pay off. The builder generates the variable-path CSS regardless, so don't reach for it until you've confirmed variable actually wins.
The tool gave you size numbers — it didn't
No measurementThis builder never reads a font, so it can't tell you the variable-vs-static byte comparison. The guidance tables here are typical patterns, not your numbers. Weigh your actual variable WOFF2 against the sum of the static weights before deciding.
All nine presets shipped but only four weights used
Harmless but tidy upLeaving all nine @font-face blocks in when you only use four costs a handful of compressed bytes of CSS — no extra font download, since they all reference the same file. It's not a performance problem, but pruning to the weights you use keeps the CSS honest about your design's weight set.
Variable file's axis is narrower than your weight set
ClampedIf you decided variable wins but the file's wght axis doesn't span every weight you need, out-of-range presets clamp to the nearest end. That can quietly negate the variable advantage (you can't actually render the Black you wanted). Confirm the axis range with font-metadata-extractor as part of the decision.
Per-page caching favours static
Context-dependentIf different pages use disjoint weight sets and users rarely cross between them, static files cache exactly what each page needs and nothing more. The variable file forces every visitor to download the whole axis even for one weight. For sites with strongly siloed weight usage, static can win even past three weights — measure per-page.
Render-blocking CSS with the variable presets inline
Watch first paintThe presets are font-display: swap, so text isn't invisible, but the variable file is one larger download. Preload it so the fetch starts with the HTML parse; otherwise the bigger file can delay the swap-in versus a smaller static critical weight. The builder doesn't emit preload — add it.
You want statics for an old engine without variable support
Variable doesn't applyIf a target renderer lacks variable-font support, presets do nothing there — font-variation-settings is ignored and you get one weight. That's a hard reason to ship statics regardless of byte counts. On the modern web platform this isn't a concern.
Expecting the tool to bake statics when static wins
Wrong toolThis builder only emits variable-path @font-face CSS. When your decision lands on static, it can't help — use variable-font-freezer to bake a static instance from the variable font, then convert to WOFF2.
Frequently asked questions
Variable presets or static files — which is smaller?
It depends on how many weights you use. One variable file is a larger single download but serves every weight; static files are smaller individually but each is a separate request and total bytes climb. Rough rule: under three weights static can win; at three-plus, one variable file with presets usually wins on total bytes and requests. Measure your real files — this tool doesn't size them.
Where's the break-even?
Around three distinct weights, give or take, depending on the font. Below that, two or three small static WOFF2 files often beat the variable file's fixed overhead. At four or more, the single cached variable file wins on both request count and total bytes, and any future weight is free.
Does this tool tell me the byte comparison?
No. It never reads a font, so it can't measure your variable file or the static alternatives. The guidance here is the typical pattern; confirm with the actual sizes of your variable WOFF2 versus the sum of the static weights you'd ship.
If static wins, can I use this builder?
No — it only generates variable-path @font-face presets. When static wins, bake the weights you need with variable-font-freezer (it produces a static instance), then convert each to WOFF2 and ship them.
Why does caching favour the variable file at higher weight counts?
Once the variable file is cached, every weight — including ones a later page introduces — is served from that single cached download with zero extra font bytes. Static files cache per weight, so each new weight a page needs is a fresh request. Across a multi-page visit using several weights, the variable file usually transfers fewer total bytes.
When does caching favour static instead?
When pages use disjoint weight sets and users rarely move between them. Then each page caches exactly the small static files it needs, while the variable file would force every visitor to download the whole axis for maybe one weight. For strongly siloed sites, measure per-page — static can win even past three weights.
Should I ship all nine presets if I use fewer weights?
You can — extra blocks cost only a few compressed CSS bytes since they all point at the same file. But pruning to the weights you actually use keeps the CSS aligned with your design. The variable file is the same either way; only the number of @font-face rules changes.
Do I need a preload tag for the variable file?
For above-the-fold text, yes. The variable file is a single larger download, so preloading it lets the fetch start with the HTML parse and minimises the swap-in delay. The builder writes only @font-face, so add the <link rel="preload" as="font" crossorigin> yourself.
What if the variable font's axis doesn't cover my weights?
Out-of-range presets clamp to the nearest axis end, so you literally can't render a weight the axis doesn't include — which can negate the variable advantage. Check the real range with font-metadata-extractor before committing to the variable path.
Does the variable path work on engines without variable support?
No — such engines ignore font-variation-settings and render one weight. If you must support one, ship static files regardless of byte math. Every modern browser since 2018 supports variable fonts, so for the web platform this is rarely the deciding factor.
Is the tool free and limited by file size?
It's free and generative — two text inputs, no upload. The font-size tiers (5 MB free / 50 MB pro) gate tools that parse binaries; this one only emits CSS, so no size limit applies to it.
If I prune the presets, does that change which weights download?
No. Pruning only removes @font-face rules from the CSS; the variable file is one resource that carries every weight regardless. So whether you keep all nine blocks or just four, the browser downloads the same single variable WOFF2 — pruning is about CSS tidiness, not bytes on the wire. The byte trade-off in the variable-vs-static decision is entirely about that one file's size versus the sum of the static alternatives.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.