How to modular scale vs arbitrary sizes: which works better
- Step 1Start modular for a new system — Generate a baseline with the [scale builder](/font-tools/typography-scale-builder): pick 16px, Major Third (1.25), 8 steps. You get `xs`–`4xl` as both static rem and fluid clamp() in one paste. Zero design judgement beyond the ratio. This is the fastest way to a coherent ramp.
- Step 2Audit your real type usage — List every distinct font-size your designs actually use, with the role beside it (hero, h1, card title, body, caption). This is the input for deciding whether the modular baseline already covers you or whether specific roles need bespoke values.
- Step 3Diff the modular baseline against real usage — Lay the generated steps next to your audit. Where a role lands within ~1px of a step, adopt the token. Where it is meaningfully off (a 48px display vs the scale's 39px/49px neighbours), that is a candidate for an arbitrary override.
- Step 4Decide per role, not globally — It is rarely all-or-nothing. Body, captions, and most headings usually fit a modular ramp cleanly. Display/hero sizes are the usual rebels because they answer to layout, not math. Keep the ramp; override the rebels.
- Step 5Encode overrides as named tokens, not magic numbers — An override is fine; an undocumented `font-size: 48px` buried in a component is not. Add `--font-size-display: 3rem` next to the generated tokens with a comment explaining why it deviates. The scale stays the source of truth; the exceptions are visible.
- Step 6Re-generate when the foundation changes — Changing the base size or ratio recomputes every modular token. Re-run the builder, re-paste the two blocks, and re-check your override list — some overrides may now coincide with a step and can be retired.
Modular vs arbitrary vs hybrid
The trade-offs along the dimensions that actually decide it in practice.
| Dimension | Modular | Arbitrary | Hybrid |
|---|---|---|---|
| Setup speed | Seconds — one ratio choice | Slow — every size is a decision | Fast baseline + a few overrides |
| Harmony | Guaranteed by construction | Depends entirely on the designer | Harmonious where it counts, exact where it must be |
| Per-role control | Low — you take what the ratio gives | Total | High — override anything that does not fit |
| Maintenance | Re-generate on base/ratio change | Hand-edit each value | Re-generate baseline, hand-manage overrides |
| Best fit | New systems, rapid prototyping, docs | Mature, opinionated brands | Most production design systems |
How three ratios diverge as you climb the scale
Same 16px base, default origin, showing why the top of a modular scale is where arbitrary overrides most often appear — the steps spread fast and may miss the exact display size a layout wants.
| Token | Minor Third (1.2) | Major Third (1.25) | Golden (1.618) |
|---|---|---|---|
base | 16px | 16px | 16px |
lg | 19.2px | 20px | 25.89px |
xl | 23.04px | 25px | 41.89px |
2xl | 27.65px | 31.25px | 67.77px |
3xl | 33.18px | 39.06px | 109.66px |
4xl | 39.81px | 48.83px | 177.42px |
What a modular generation gives you vs what it cannot
The JAD builder produces the modular half. Knowing its boundaries tells you exactly where arbitrary work begins.
| Capability | From the builder? | Notes |
|---|---|---|
| Full ramp from one ratio | Yes | Static rem + fluid clamp() in one type-scale.css. |
| Per-role override values | No | You add these by hand alongside the generated tokens. |
| Arbitrary (non-preset) ratio | Via runner API only | The page UI is an 8-option dropdown; the API takes a numeric scaleRatio. |
| Custom token names | No | Names are fixed xs–8xl; rename in your editor after pasting. |
| Element mapping (h1→token) | No | Output is variables only; you assign them to elements. |
Cookbook
Concrete comparisons: the same hierarchy expressed modularly (generated) and arbitrarily (hand-tuned), and the hybrid that most teams ship. The generated blocks are exactly what the scale builder emits. For wrapping these in a fuller variable set (line-height, spacing) see the font CSS variable generator.
Pure modular baseline (generated, untouched)
ExampleMajor Third at 16px, 8 steps — straight from the builder. Every size on the ratio. This is the harmonious starting point you override from, not necessarily what ships.
/* base: 16px · ratio: 1.25 · steps: 8 — generated */
:root {
--font-size-xs: 0.640rem; /* 10.24px */
--font-size-sm: 0.800rem; /* 12.8px */
--font-size-base: 1.000rem; /* 16px */
--font-size-lg: 1.250rem; /* 20px */
--font-size-xl: 1.563rem; /* 25px */
--font-size-2xl: 1.953rem; /* 31.25px */
--font-size-3xl: 2.441rem; /* 39.06px */
--font-size-4xl: 3.052rem; /* 48.83px */
}Pure arbitrary scale (hand-picked)
ExampleThe same roles, sizes chosen by eye and by layout constraints. Note 44px and 30px — neither sits cleanly on a 1.25 ratio from 16. Total control, zero guaranteed harmony.
/* Designer-picked, no ratio constraint */
:root {
--fs-caption: 0.75rem; /* 12px */
--fs-body: 1rem; /* 16px */
--fs-lead: 1.125rem; /* 18px */
--fs-h3: 1.5rem; /* 24px */
--fs-h2: 1.875rem; /* 30px */
--fs-h1: 2.75rem; /* 44px — hero needs this exact size */
}Hybrid: modular base + documented overrides
ExampleThe pattern most production systems converge on. Keep the generated ramp; add a couple of named exceptions where the layout demanded something off-ratio, each with a comment.
/* Generated modular ramp (Major Third, 16px) */
:root {
--font-size-xs: 0.640rem;
--font-size-sm: 0.800rem;
--font-size-base: 1.000rem;
--font-size-lg: 1.250rem;
--font-size-xl: 1.563rem;
--font-size-2xl: 1.953rem;
--font-size-3xl: 2.441rem;
--font-size-4xl: 3.052rem;
/* Documented overrides — off-ratio by design */
--font-size-hero: 2.75rem; /* 44px: 4xl(48.83) too big, 3xl(39) too small */
--font-size-eyebrow: 0.6875rem; /* 11px: tighter than xs for kicker labels */
}Check whether an arbitrary scale is secretly modular
ExampleIf consecutive sizes divide to roughly the same number, your hand-picked scale is already near-modular and can be regularised. Here the ratios cluster near 1.25 — adopt Major Third and most values barely move.
Existing arbitrary sizes: 16, 20, 24, 31, 39 Consecutive ratios: 20 / 16 = 1.25 24 / 20 = 1.20 31 / 24 = 1.29 39 / 31 = 1.26 Mean ≈ 1.25 → adopt Major Third; only the 24 (vs 25) shifts.
Use the runner for an off-preset ratio
ExampleIf your brand wants 1.2 → 1.3 'in between', the page dropdown cannot do it, but the runner API takes a raw number. Useful when migrating an existing arbitrary scale to the nearest clean modular one.
POST http://127.0.0.1:9789/v1/tools/typography-scale-builder/run
Content-Type: application/json
{ "options": { "baseSize": 16, "scaleRatio": 1.27, "steps": 8 } }
# returns the same two-block CSS, computed at ratio 1.27Edge 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.
A role needs a size that falls between two modular steps
ExpectedThis is the single most common reason teams add arbitrary overrides. A 48px display lands awkwardly between Major Third's 3xl (39px) and 4xl (49px). The honest fix is a named override (--font-size-display: 3rem) next to the generated tokens — keep the harmonious ramp, document the exception.
You want a non-preset ratio for a near-modular brand scale
By designThe page's Ratio control offers eight fixed presets — no 1.27 or 1.35. The handler itself accepts any numeric scaleRatio, so the runner API can compute an arbitrary ratio. Pick the nearest preset for a quick start, or hit the API when you are regularising an existing arbitrary scale to a clean modular one.
Arbitrary scale has no internal consistency and breaks on resize
Watch outHand-picked sizes with no shared logic tend to grow unevenly under fluid scaling — you end up writing a bespoke clamp() per size. The clamp() generator handles individual fluid values, but a modular baseline gives you a coherent fluid ramp for free. Mixing both is fine; just be deliberate about which sizes are fluid.
Modular scale's top steps are unusably large
ExpectedA dramatic ratio (Golden 1.618) spreads fast — 4xl can exceed 170px at 16px base. That is not a bug; it is the ratio compounding. Either reduce the step count, choose a gentler ratio, or cap the display sizes with arbitrary overrides. The builder's Largest metric warns you before you copy.
Changing the ratio later rewrites every size
Watch outBecause every modular value derives from base × ratio, switching ratios mid-project recomputes the entire ramp — every component that referenced a token shifts. Arbitrary scales avoid this (each value is independent) at the cost of harmony. Decide the ratio early; the hybrid approach localises later churn to the override list.
Token names do not match your existing system
By designThe generated names are xs–8xl. If your system uses --text-200 or --fs-lg, the tool will not rename them — do a prefix find-and-replace after pasting. The values transfer cleanly; only the labels need adjusting.
Designer hands you sizes that are already a clean ratio
SupportedSometimes an 'arbitrary' scale is secretly modular — divide consecutive sizes and if they cluster around one number, adopt that ratio and regenerate. You keep the designer's intent and gain a single source of truth. The cookbook above shows the divide-and-average check.
You expected the tool to map sizes to h1–h6 automatically
By designThe builder outputs CSS variables only — it does not write h1 { font-size: ... } rules. Whether modular or arbitrary, you map tokens to elements yourself. This keeps the output framework-agnostic and lets you decide which step each role gets.
Frequently asked questions
Is a modular scale always more harmonious than an arbitrary one?
By construction it is internally consistent — every step differs from its neighbour by the same ratio, which reads as visual rhythm. Whether that specific rhythm suits your brand is subjective. An arbitrary scale can look just as good if a skilled designer tuned it; it just has no guarantee and no single knob to maintain it.
When should I prefer arbitrary sizes?
When you have observed, real-world size needs that a ratio cannot hit cleanly — a hero that must be exactly 44px, a caption that has to be 11px for a dense table. Mature, opinionated brands often run mostly arbitrary because their layouts dictate sizes. Even then, most keep a modular spine and override the exceptions.
What does 'hybrid' actually look like in code?
A generated modular ramp (--font-size-xs…4xl) plus a short list of named overrides (--font-size-hero, --font-size-eyebrow) with a comment on each explaining why it deviates. The cookbook above has a full example. The ramp stays the source of truth; the exceptions are visible and few.
Does the JAD builder do arbitrary scales?
No — it generates modular ramps from base × ratio^n. It gives you the modular half of a hybrid; the arbitrary overrides you write by hand alongside the generated tokens. The output is plain CSS variables, so mixing in your own values is trivial.
Can I tell if my current scale is already modular?
Divide each size by the one below it. If the results cluster around a single number (say all near 1.25), your scale is effectively modular and you can adopt that ratio and regenerate. If they scatter (1.1, 1.4, 1.2…), it is genuinely arbitrary.
How do I get an in-between ratio the dropdown does not list?
The page offers eight presets only. For a value like 1.27, call the tool through the JAD runner's API with a numeric scaleRatio — the underlying handler accepts any positive number. The runner request shape is in the cookbook above and the build-pipeline guide.
Will switching from arbitrary to modular break my layouts?
Some sizes will shift by a few px as they snap to ratio steps. Diff the generated ramp against your real usage first (the how-to steps cover this), adopt tokens where they land within ~1px, and keep arbitrary overrides for the rest. The change is usually small and improves consistency.
Does fluid scaling work for both approaches?
Yes. The builder's fluid clamp() block covers the modular ramp automatically. For arbitrary sizes you build individual clamp() values with the clamp() generator. A hybrid uses the generated fluid block for the ramp and per-value clamps for the overrides.
Which is better for a brand-new product?
Modular, almost always. You get a coherent ramp in seconds with one decision (the ratio), which is exactly what an early system needs. Add arbitrary overrides later as real layout needs surface. Starting fully arbitrary on day one means bikeshedding every size with no data.
How many sizes does a typical system need?
Most ship 6–10 steps. The builder's slider runs 3–12. A dense product UI might use 6; an editorial site with big display type might use 10–12. Generate more than you think you need — unused tokens cost nothing and save you re-running when a new role appears.
Can I document overrides so the team respects them?
Put them in the same file as the generated tokens, named and commented (--font-size-hero: 2.75rem; /* off-ratio: layout demands 44px */). Reviewers then see the exception and its reason in one place. Undocumented magic numbers in components are what erode a scale over time.
Is there an objectively correct ratio?
No. Major Third (1.25) is the safe, popular default and a fine starting point. Editorial and luxury brands lean dramatic (Perfect Fifth, Golden); reading-heavy sites lean subtle (Minor Third). The brand-personality guide maps tones to ratios; the ratios reference lists all eight with values.
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.