Every hand-picked font size is a decision nobody documented, and decisions that aren't documented drift. A modular scale replaces them with a base, a ratio, and a rule — then gets out of your way.
Modular scales in typography borrow directly from music. Just as an octave is a 2:1 frequency ratio and a perfect fifth is 3:2, a typographic scale steps up by a fixed ratio: 4:3 (perfect fourth, 1.333), 3:2 (perfect fifth, 1.5), and so on. Renaissance printers used these proportions to set type that felt related across sizes; the practice was revived on the web because it solves the same problem — making twelve sizes look like they belong to one family.
The formula is the whole system:
size = base × ratiostep
Generate yours with the type scale calculator — pick a base and a ratio, and every step follows.
The base is your body copy, and it is the one number that should not be negotiable per-page.
Express the base in absolute terms once, then work in rem everywhere else so that users who raise their browser default get a proportional result rather than a broken layout.
| Ratio | Name | Feels like |
|---|---|---|
| 1.067 | Minor second | Flat, dense, technical |
| 1.125 | Major second | Compact, app-like |
| 1.200 | Minor third | Balanced, common default |
| 1.250 | Major third | Clear hierarchy, safe |
| 1.333 | Perfect fourth | Confident, editorial |
| 1.500 | Perfect fifth | Dramatic |
| 1.618 | Golden ratio | Display only, in practice |
The honest summary: most products land between 1.2 and 1.333. Below that, headings stop reading as headings; above it, the top of the scale runs away from you on anything but a marketing page.
Generate eight steps, ship five or six. Every additional near-identical size is an invitation for two authors to choose differently, and that divergence is precisely what the scale existed to prevent.
A scale gives you sizes. Spacing is a separate decision, and it should move in the opposite direction: as type gets larger, line height gets tighter.
Line length and type size are coupled. The classical guidance — 45 to 75 characters per line, with around 66 often cited as the sweet spot — is about eye travel: too short and the eye resets constantly, too long and it loses the start of the next line.
This is why simply enlarging body text can make a page harder to read. If you raise the base from 16px to 18px inside a fixed-width column, your measure drops and the rhythm changes. Either widen the column, or accept the shift deliberately.
A fixed scale is awkward across a 360px phone and a 1600px monitor. The modern answer is clamp(), which interpolates between a minimum and maximum using a preferred value tied to viewport width:
font-size: clamp(1rem, 0.875rem + 0.6vw, 1.25rem);
Three rules keep fluid type from becoming chaotic:
rem component in the preferred value. A preferred value expressed purely in vw breaks browser zoom for users who need it.Define the scale once as custom properties, and let components reference tokens rather than raw values:
:root {
--scale-base: 1rem;
--scale-ratio: 1.25;
--step-1: calc(var(--scale-base) / var(--scale-ratio));
--step-2: var(--scale-base);
--step-3: calc(var(--scale-base) * var(--scale-ratio));
--step-4: calc(var(--step-3) * var(--scale-ratio));
}
Now a brand refresh is two numbers instead of a search-and-replace across forty files. And because everything is expressed in rem, a user with a 20px browser default gets the entire system scaled up proportionally.
Scale maths: size = base × ratiostep. Guidance on measure reflects long-standing typographic practice rather than a formal specification; adapt it to your typeface, script and audience.