Skip to main content
CSS

Modular type scales in CSS: pick a ratio, then check it against real copy

Multiply a base size by a fixed ratio per step and headings gain a relationship. Which ratio to pick, why golden gets ugly in UI, and the mobile check people skip.

Thien Nguyen
By Thien Nguyen
Updated July 21, 2026 · 2 min read

Multiply your base font size by a fixed ratio for each step up the hierarchy, and the sizes stop looking arbitrary — that repeated multiplication is a modular scale. Start from 16px body text and a ratio of 1.25, and each step is the last one times 1.25: 16 → 20 → 25 → 31.25 → 39. The headings now share a relationship instead of being five numbers someone picked on five different afternoons.

:root {
  --step-0: 1rem;      /* 16px  body */
  --step-1: 1.25rem;   /* 20px */
  --step-2: 1.563rem;  /* 25px */
  --step-3: 1.953rem;  /* 31.25px */
}
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }

The ratio is the whole decision

RatioName16px steps upFeel
1.2Minor third16 → 19.2 → 23 → 27.6Tight, good for dense UI
1.25Major third16 → 20 → 25 → 31.25Balanced, safe default
1.333Perfect fourth16 → 21.3 → 28.4 → 37.9Editorial, roomy
1.618Golden ratio16 → 25.9 → 41.9 → 67.8Dramatic, breaks in UI

The golden ratio looks authoritative in a blog post and falls apart in an actual product. By the third step you're at 42px, and by the fourth you're near 68px — fine for a marketing hero, unusable for an h4 in a settings panel. Denser interfaces want 1.2–1.25; give editorial layouts with a lot of vertical space the bigger jumps.

A scale is a starting grid, not a law. Nothing says every heading must land exactly on a step — if h4 at 27.6px crowds h3, nudge it. The scale exists to kill arbitrary values, not to override your eyes.

The check almost everyone skips is narrow widths. A ratio that reads beautifully at 1440px can wrap an h1 to four ragged lines on a 375px phone. Test your real headlines — the longest actual title in your CMS, not "Lorem ipsum" — at mobile widths before you commit. If you want the scale to breathe between breakpoints, clamp() interpolates a step fluidly: font-size: clamp(1.5rem, 1.2rem + 1.5vw, 1.953rem) grows the size with the viewport instead of snapping at a media query.

The point isn't mathematical purity. It's that the next person to add a page inherits a small set of semantic steps and reaches for one of them, instead of typing font-size: 22px because it looked about right.

Cover photo by Stanislav Kondratiev on Pexels.

References

Primary documentation and specifications checked when this article was last updated.

CSSTypographyDesign

Related articles

All articles