How to pick heading, body, and accent weights by seeing them all at once
- Step 1Load your body-copy font — Upload the variable (or static) family you plan to use for running text. The viewer reads its `fvar` table to enumerate weights.
- Step 2Paste real product copy — Replace the default `The quick brown fox` with the strings you actually set: a sentence of body copy, a card title, a CTA label, and a price like `$1,299/mo`. Judging weight on your own glyphs beats a generic pangram.
- Step 3Render the full progression — The viewer stacks one row per weight at 36px. For a variable font you'll see named instances or 100-unit axis steps; for a static file, the single weight it carries.
- Step 4Pick the body weight first — Scan for the lightest weight that still holds at body sizes without looking thin on your background. Note its `font-variation-settings` value from the label.
- Step 5Pick heading and accent weights for contrast — Choose a heading weight with clear contrast against your body weight, and an accent (e.g. for labels or emphasis) that sits between them. The single-view layout makes the gaps obvious.
- Step 6Record the chosen values — Copy the three `font-variation-settings` strings into your stylesheet or token file. The viewer outputs a self-contained HTML you can keep as the reference for the decision.
Weights you actually have to choose from
The viewer's row list is the menu you choose from. What appears depends entirely on the font's fvar table.
| Font shape | Rows you see | What to pick from them |
|---|---|---|
| Named-instance variable font | Thin, Light, Regular, Medium, SemiBold, Bold, Black (whatever fvar defines) | Map body→Regular/Medium, heading→SemiBold/Bold, accent→between |
| Continuous wght variable font (no instances) | Every 100 from ceil(min/100)*100 to max | You can also choose off-grid values (e.g. 450) — the rows are guides, not the only legal values |
| Static single weight | One Static row at font-weight: 400 | You only have that one weight; pair it with a second family or a separate file |
A starting-point weight map (verify it in the viewer)
Common role-to-weight mappings to test against your own copy. These are conventions, not output of the tool — confirm each by eye in the rendered stack.
| Role | Typical weight | What to check in the preview |
|---|---|---|
| Body text | 400–450 | Stays comfortable at small sizes, not thin on dark backgrounds |
| Subheading | 500–600 | Reads as distinct from body without shouting |
| Heading | 600–700 | Holds shape at large sizes; 700 can blob at small sizes |
| Accent / label | 500–600 + caps | Legible at small caps sizes; numerals stay even |
| Display / hero | 800–900 | Only if the font's max reaches it — check the top row exists |
Cookbook
Five concrete weight-selection sessions. Each starts from what the viewer renders and ends with the three values you'd commit. Numbers are illustrative — always confirm against your own font's rendered rows.
Dashboard UI: tuning body weight up off 400
ExampleOn dark dashboards, 400 can read thin. Previewing 400 next to 450 and 500 in your own copy often shifts body to 450.
Sample text: Monthly recurring revenue grew 12% MoM Rendered rows compared: wght 400, wght 450, wght 500 Decision: body font-variation-settings: "wght" 450; heading font-variation-settings: "wght" 650; accent font-variation-settings: "wght" 550;
Marketing hero: confirming the family reaches 900
ExampleBefore designing a big hero around Black, check the viewer actually renders a top row at 900 — the axis max may stop short.
Sample text: Ship faster. If the top rendered row is 'wght 800', the axis max < 900. Then pick: hero font-variation-settings: "wght" 800; (don't spec 900 the font can't reach)
Numeral-heavy pricing page
ExampleSet a price string as the sample so you judge weight on figures, where thin weights lose the comma and decimal.
Sample text: $1,299.00 /year Scan rows for the lightest weight where the comma and decimal stay solid: price font-variation-settings: "wght" 500; label font-variation-settings: "wght" 600;
Named-instance family: mapping roles to instances
ExampleWhen the font defines named instances, map UI roles to the instance whose settings string you'll copy verbatim.
Rows: Light, Regular, Medium, SemiBold, Bold
Map:
body -> Regular ("wght" 400)
heading -> SemiBold ("wght" 600)
strong -> Bold ("wght" 700)Static-only font: realising you need a second weight
ExampleIf the viewer shows a single 'Static' row, the file gives you one weight. Plan to load a second file or family for contrast.
Rendered: 1 row -> Static (font-weight: 400) Decision: body uses this file; for headings load a separate Bold file (this single-file viewer can't compare the two — preview each on its own).
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.
Static font shown as one Regular-looking row
Single Static row at 400A static file renders exactly one row labelled Static at font-weight: 400, even if the file is actually a Bold. The viewer applies 400 in the fallback, so don't read the rendered weight as the file's true weight — read its name table elsewhere.
Picking a weight the font can't reach
Top step may be missingIf the axis max isn't a multiple of 100 (say 850), the top rendered row is wght 800. Don't spec "wght" 900 for a hero if no row shows it — the browser will clamp to the axis max.
Wanting an off-grid weight like 450
Valid, just not a rendered rowOn a continuous axis you can specify any value in range; the 100-unit rows are guides. If 450 reads best between the 400 and 500 rows, use "wght" 450 even though no row shows it exactly.
Expecting the tool to output CSS tokens
Not producedThe viewer renders a preview and gives you copy-ready font-variation-settings values, but it does not emit token files or CSS custom properties. Use the css variable generator for that step.
Comparing body weights on light vs dark
Single background onlyThe preview renders white text on the tool's dark surface. To judge a body weight on a light background you'll need to eyeball it in your own page — the viewer doesn't toggle background colour.
Sample text too long to read per row
Renders as givenVery long sample strings still render at 36px and may wrap or overflow the row. Keep samples to the phrase you're actually judging (a title, a price), not whole paragraphs.
Named instances out of weight order
Rendered in fvar orderRows follow the order instances appear in fvar, which is usually but not always ascending by weight. Read the settings label, not the row position, to know each row's weight.
Font has duplicate weights across instances
Both shownIf two named instances share a wght (e.g. Bold and Condensed Bold), both rows appear; their settings strings differ on the other axis, which is the contrast you're choosing between.
Frequently asked questions
Does the viewer recommend which weights to use?
No — it shows every available weight in your own copy so you can decide. The role-to-weight mappings in this guide are conventions to test, not the tool's output.
Can I judge a weight against my brand copy?
Yes — paste your real strings into the Sample text box. Every weight row then renders that exact text at 36px.
Why does my Bold static font preview at a normal weight?
A static file with no fvar falls back to a single row at font-weight: 400. The rendered weight there is 400 regardless of the file's actual style — check the name table with the font metadata extractor to confirm its real weight.
Can I pick a weight like 450 that has no row?
Yes, on a continuous wght axis. The 100-unit rows are guides; any value within the axis range is valid in font-variation-settings.
Does it output CSS variables or design tokens?
No. It gives you the font-variation-settings values to copy. To turn them into reusable CSS custom properties, use the css variable generator.
Can I compare two separate font files for contrast?
No — it's single-file. Preview each font on its own and compare the saved HTML outputs side by side.
What size are the rows rendered at?
36px, fixed. For responsive heading/body sizing, pair your weight choice with the clamp font size generator.
Will it show all named instances or just weight ones?
It shows every named instance defined in fvar. If a family defines width or optical-size instances too, they appear, with their full coordinate strings.
Can I preview on a light background?
Not directly — the preview uses light text on a dark surface. Confirm a body weight on light backgrounds in your own page.
What's the largest font I can upload?
5 MB on the free tier. WOFF2 versions are usually well under that.
Does choosing a heavier body weight hurt file size?
Not for a variable font — the whole range ships in one file regardless of which weight you set. The weight you pick has no extra download cost.
How do I know the font even has the weights I want?
Run the viewer: the rendered rows are the authoritative menu. If there's no row near the weight you want, the font doesn't expose it.
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.