Building a type scale that survives contact with real content

Design · 5 min read

A type scale looks simple on a design system slide: a tidy list of sizes from small to large, each one a clean multiple of the last. Real content is messier than that slide, with long headlines, short labels and everything in between, and a scale that only looks good in the mockup will keep breaking once real copy arrives.

Why a modular scale beats picking sizes by eye

A modular scale generates font sizes by multiplying a base size by a fixed ratio repeatedly, such as 1.25 for a 'major third' scale. This produces a set of sizes with a consistent visual relationship, so a heading always feels like a deliberate step up from the text below it rather than an arbitrary jump.

Picking sizes by eye tends to produce scales that are inconsistent under scrutiny, with steps that are sometimes too close together and sometimes too far apart. A ratio-based approach removes that guesswork and gives you a defensible reason for every size in the system.

Choosing a base size and a ratio

Sixteen pixels is still the most sensible default base size for body text on the web, matching most browsers' default and keeping accessibility zoom behaviour predictable. From there, a ratio between 1.125 and 1.333 works well for most interfaces; smaller ratios like 1.125 suit content-dense apps, while larger ratios like 1.333 suit marketing pages that want more dramatic headline sizes.

Avoid ratios much above 1.5 unless you genuinely want only a handful of very distinct sizes, since large ratios quickly produce headline sizes that are impractical on smaller screens.

Why rem beats pixels for font sizes

Sizing text in rem units ties every size in your scale to the user's root font size, which respects any accessibility zoom or browser font-size preference the user has set. Sizing in pixels overrides that preference, effectively locking out users who rely on larger default text for readability.

Because rem values are relative multiples, converting your modular scale's pixel values into rem is a one-time calculation, easiest done with a unit calculator, and after that every size in the system keeps working correctly regardless of the user's base font size.

Line height needs its own scale

Line height should generally shrink as font size grows, not stay fixed. A large headline needs proportionally less line height than small body text, because longer lines of small text need extra vertical space to remain scannable, while short headline lines do not.

A workable rule of thumb is roughly 1.5 line height for body text sizes, tapering down to around 1.1 or 1.2 for your largest headline sizes. Treat this tapering as part of the type scale itself, not an afterthought applied separately.

Testing the scale against real headline lengths

Before finalising a scale, test your largest sizes against genuinely long real-world headlines, not a short punchy placeholder. A headline size that looks striking with four words can look absurd, or force awkward wrapping, with a realistic twelve-word headline from actual content.

This is one of the clearest cases where testing with realistic placeholder text, rather than lorem ipsum, pays off, since lorem ipsum's evenly distributed word lengths rarely produce the length extremes real headlines do.

Responsive scaling without a mess of media queries

Rather than manually setting a different font size for every heading at every breakpoint, use CSS clamp to let a size scale smoothly between a minimum and maximum value based on viewport width. This produces genuinely fluid type without the visible jumps that fixed breakpoints create.

Keep your minimum and maximum values grounded in your rem-based modular scale, so the fluid sizes still relate sensibly to the rest of the type system rather than becoming an arbitrary one-off.

Keeping the number of sizes manageable

A common mistake is generating far more sizes than a real interface needs, simply because the ratio produces them. Most products function well with six to eight sizes total: a couple of body text sizes, a caption or label size, and three or four heading sizes.

Every additional size in a design system is a small ongoing cost in decision-making and consistency. Resist the urge to add a size for every slightly different context; reuse existing steps wherever the difference is marginal.

Naming sizes for how they are used, not how they look

Name your scale steps by role, such as 'body', 'body-large', 'heading-sm', 'heading-lg', rather than purely numeric labels like 'text-1' through 'text-8'. Role-based names make it much easier for anyone using the system to pick the right size without needing to remember which number corresponds to which use case.

This also makes future changes safer: if you decide to bump the base body size slightly, updating the value behind 'body' updates every correct usage automatically, without anyone needing to hunt down a specific number across the codebase.

Converting and checking values as you build

Whether you are converting your modular scale from pixels to rem, checking a clamp function's minimum and maximum against a target viewport, or converting a line height percentage into a unitless value, a unit calculator saves repeated manual arithmetic and reduces the chance of a rounding mistake making its way into production CSS.

Common questions

What font size should I use as the base for a type scale?
Sixteen pixels is the standard, sensible default for body text on the web. It matches most browsers' built-in default size, keeps text readable without zooming, and behaves predictably when a user increases their font size preference for accessibility.
Should I size text in pixels or rem?
Use rem. Pixel sizes ignore a user's browser font-size preference, which can make text inaccessible for people who rely on larger default sizes. Rem values scale relative to the root font size, so accessibility preferences are respected automatically.
How many sizes should a type scale have?
Most interfaces work well with six to eight sizes covering body text, captions and a handful of heading levels. Generating every size a modular ratio produces without limit tends to create unnecessary decisions and inconsistency rather than a genuinely useful system.
Should line height be the same at every font size?
No. Line height should generally decrease as font size increases, with body text sitting around 1.5 and large headlines tapering down towards 1.1 or 1.2. Treat this tapering as part of the type scale rather than a separate, ad hoc adjustment.
How do I make headline sizes responsive without lots of media queries?
Use the CSS clamp function to let a font size scale smoothly between a minimum and maximum value across viewport widths. This produces fluid type without visible jumps at fixed breakpoints, and keeps the sizing logic in one place rather than scattered across multiple media queries.

Tools for this

Keep reading