Tags: web-dev concept

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: 17px in 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-16 breaks the moment the base changes; font-base doesn’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.