Type Scale
Date: 2026-08-16
A fixed set of font sizes derived from a base and a ratio, chosen from rather than invented per screen. It exists because sizes picked by eye cluster into near-duplicates that read as sloppiness without anyone being able to say why.
A type scale is a bounded list of font sizes, generated by repeatedly multiplying a base size by a ratio, that every piece of text must choose from.
Generating one
base 16px
ratio 1.25 (the "major third")
16 × 1.25 = 20
20 × 1.25 = 25
25 × 1.25 = 31.25
31.25 × 1.25 = 39.06
downwards
16 ÷ 1.25 = 12.8
Rounded and named:
xs 13px
sm 14px
base 16px
lg 20px
xl 25px
2xl 31px
3xl 39px
4xl 49px
Round to whole pixels. Sub-pixel sizes render inconsistently and buy nothing.
Choosing the ratio
1.125 minor second very tight
1.200 minor third subtle
1.250 major third the safe default
1.333 perfect fourth clear hierarchy
1.500 perfect fifth dramatic
1.618 golden ratio editorial, few steps
Larger ratios give clearer hierarchy and fewer usable steps. A 1.618 scale jumps 16 → 26 → 42, which is striking for a marketing page and unusable for an interface with six levels of heading.
Interfaces want tight ratios; editorial wants wide ones. A dashboard on a 1.5 scale has a headline four times the size of its labels and no room in between.
Line height belongs with size
Line height is not one number. It varies inversely with size:
size line-height ratio
13px 18px 1.4
16px 24px 1.5
20px 28px 1.4
31px 38px 1.2
49px 54px 1.1
Small text needs proportionally more leading; large text needs less. A single line-height: 1.5 across the scale makes headings look loose and disconnected.
Pair them in the token, so choosing a size gives you the line height automatically — Design Tokens:
font.size.lg → 20px / 28px
Fluid type
Sizes that scale with viewport rather than stepping at breakpoints — the clamp() arithmetic and the zoom caveat are in Fluid Type and Space:
--font-size-3xl: clamp(
1.75rem, /* min */
1.2rem + 2.5vw, /* preferred */
2.5rem /* max */
);Worth it for the top two or three steps only. Body text should not scale with viewport — it’s already at a comfortable reading size, and shrinking it on mobile is exactly wrong.
Always set a maximum. Unbounded vw type produces absurd headlines on wide monitors.
Where it goes wrong
- Too many steps. Nine is plenty. Fourteen means several are within 2px of each other and nobody can tell which to use
- Escape hatches. One
font-size: 17pxin a component and the scale is advisory rather than binding - Size as the only hierarchy signal. Weight, colour and spacing do much of the work, and reaching for size first produces interfaces that are all shouting — Spacing Systems
- Ignoring the font’s own metrics. Two fonts at 16px can differ substantially in apparent size, so a scale tuned for one needs rechecking if the typeface changes
- Naming by pixel value.
font-16breaks the moment the base changes;font-basedoesn’t
The honest limit
A scale makes sizes consistent. It does not make hierarchy correct — that’s a decision about what matters on the page, and a well-generated scale applied to a badly-ordered page produces a tidy mess.