PRACTICAL GUIDES · 7 MIN READ

Build a typography scale that feels like a system

Build a type scale: pick a base size and a ratio, compute the steps in rem, make headings fluid with clamp(), and ship it as CSS or Tailwind tokens.

A typography scale is a short list of font sizes generated by multiplying a base size by a fixed ratio. Start from a 1rem body size, choose a ratio between about 1.125 and 1.333 for most websites, keep five to eight steps, and give every step a role and its own line height.

Why use a scale at all

Open the stylesheet of a site that grew without a plan and you will find 13px, 14px, 15px, 17px and 18px, each added on a different afternoon. Every size made sense on its own. Together they blur the hierarchy, because a reader cannot tell a 17px heading from 16px body text.

A scale replaces those decisions with one. Sizes that share a ratio look related, in the way notes in a musical scale sound related, which is where the ratio names come from. It also gives a team a shared vocabulary: “step 3” instead of “that biggish heading”.

Step 1: begin where people read

The base of the scale is your body text, because that is where readers spend their time. Choose it using real content in the intended layout. Consider the typeface’s proportions: a font with a small x-height looks smaller than another at the same font-size. Consider how far readers are from the screen too.

For most sites the right answer is 1rem. One rem equals the browser’s default font size, which is 16px unless the person has changed it. People who raise that setting did it for a reason. A base value is a design starting point, not a reason to override someone’s reading preferences.

/* Avoid: replaces the reader's preferred size with yours */
html {
  font-size: 16px;
}

/* Better: leave the root alone and build on rem */
body {
  font-size: 1rem;
  line-height: 1.6;
}

If your design file is in pixels, convert with the px to rem converter and keep the rem values in code.

Step 2: choose a ratio and generate the steps

A modular scale multiplies the base size by a ratio for each step up, and divides by it for each step down. Smaller ratios create subtle differences. Larger ratios create a more dramatic hierarchy.

RatioNameStep 4 from 16pxGood for
1.067Minor second20.74pxVery dense interfaces where sizes barely differ
1.125Major second25.63pxApps, dashboards, data-heavy screens
1.2Minor third33.18pxProduct interfaces, documentation, mobile layouts
1.25Major third39.06pxA dependable default for content sites
1.333Perfect fourth50.52pxBlogs, editorial and marketing pages
1.414Augmented fourth63.96pxBold marketing pages with short headlines
1.5Perfect fifth81pxLanding pages and posters with few sizes
1.618Golden ratio109.66pxDisplay work. Too steep for most interfaces
Step 4 is the base multiplied by the ratio four times.

Here is the full calculation for a 16px base with a 1.25 ratio. Each size is the base times the ratio raised to the step number.

StepCalculationPixelsrem
-216 ÷ 1.25 ÷ 1.2510.240.64
-116 ÷ 1.2512.80.8
016161
116 × 1.25201.25
220 × 1.25251.563
325 × 1.2531.251.953
431.25 × 1.2539.062.441
539.06 × 1.2548.833.052
648.83 × 1.2561.043.815

Use the type scale calculator to see these relationships with your own base and ratio before writing CSS. Two practical notes. Step -2 is about 10px, which is too small for most text, so you would simply not use it. And rounding is fine: nobody can see the difference between 1.953rem and 1.95rem.

Step 3: assign roles and line heights

A list of numbers is not a system until each one has a job. Map the steps to roles, and you do not need to use every generated value. Five to eight sizes cover most sites.

StepSizeRoleLine height
-10.8remCaptions, labels, footnotes1.5
01remBody text1.6
11.25remLead paragraph, small headings1.5
21.563remSubsection heading1.3
31.953remSection heading1.25
42.441remPage title1.15
53.052remHero or display1.1

Notice that line height shrinks as size grows. Review line height alongside font size, because a heading at body line height looks like it is falling apart. The reasoning is in line height and letter spacing.

Size is not structure Keep semantic HTML separate from visual size. A heading’s level should reflect the document outline, even when the design gives an h2 a smaller or larger style. Name your tokens by step or by role, not by tag.

Step 4: refine at narrow widths with clamp()

A scale that feels balanced on desktop can overwhelm a phone. A 61px headline leaves room for only a word or two per line on a small screen. Check long headlines and navigation labels at narrow widths. You have two options: switch to a smaller ratio below a breakpoint, or let the large steps scale smoothly with the viewport.

clamp(min, preferred, max) does the second. The preferred value mixes a rem part and a vw part so the size grows in a straight line between two viewport widths. The formula is:

  • slope = (max size - min size) ÷ (max viewport - min viewport)
  • intercept = min size - slope × min viewport
  • preferred value = intercept, converted to rem, plus slope × 100, written in vw

Worked example: a page title that should be 32px (2rem) on a 320px screen and 56px (3.5rem) at 1280px. The slope is (56 - 32) ÷ (1280 - 320) = 0.025, which is 2.5vw. The intercept is 32 - 0.025 × 320 = 24px, which is 1.5rem.

h1 {
  /* 2rem at 320px wide, 3.5rem at 1280px wide, linear in between */
  font-size: clamp(2rem, 1.5rem + 2.5vw, 3.5rem);
  line-height: 1.1;
}
Check: at 320px, 1.5rem + 2.5vw is 24 + 8 = 32px. At 1280px it is 24 + 32 = 56px.
  • Always include a rem part in the preferred value. A size in vw alone ignores the reader’s font size setting and barely responds to zoom.
  • Keep body text fixed or nearly fixed. Fluid sizing is for the top of the scale, where the difference between phone and desktop is large.
  • Write the minimum and maximum in rem as well, so the whole expression follows the user’s settings.

Step 5: turn the scale into tokens

Translate the final choices into reusable tokens so arbitrary values stop appearing in your stylesheets. In plain CSS, custom properties are enough.

:root {
  --step--1: 0.8rem;
  --step-0: 1rem;
  --step-1: 1.25rem;
  --step-2: 1.563rem;
  --step-3: 1.953rem;
  --step-4: clamp(2rem, 1.7rem + 1.5vw, 2.441rem);
  --step-5: clamp(2.25rem, 1.85rem + 2vw, 3.052rem);
}

body {
  font-size: var(--step-0);
  line-height: 1.6;
}

h1 {
  font-size: var(--step-5);
  line-height: 1.1;
}

h2 {
  font-size: var(--step-3);
  line-height: 1.25;
}

small,
figcaption {
  font-size: var(--step--1);
  line-height: 1.5;
}

In Tailwind CSS version 4, the same scale goes into the theme as --text-* variables. A companion variable sets the default line height for each size, so text-3xl brings the right leading with it.

@import "tailwindcss";

@theme {
  --text-sm: 0.8rem;
  --text-sm--line-height: 1.5;
  --text-base: 1rem;
  --text-base--line-height: 1.6;
  --text-lg: 1.25rem;
  --text-lg--line-height: 1.5;
  --text-xl: 1.563rem;
  --text-xl--line-height: 1.3;
  --text-2xl: 1.953rem;
  --text-2xl--line-height: 1.25;
  --text-3xl: 2.441rem;
  --text-3xl--line-height: 1.15;
  --text-4xl: 3.052rem;
  --text-4xl--line-height: 1.1;
}
In Tailwind 3 the equivalent lives under theme.extend.fontSize in tailwind.config.js.

Sizes are one half of the system. The other half is the typefaces they are applied to, which we cover in how to pair fonts.

Reverse-engineer the scale of a site you like

A good way to choose a ratio is to find out what a site you admire uses. You can work it out by hand.

  1. Right-click the body text, choose Inspect, open the Computed tab and note font-size.
  2. Repeat for each heading level, the lead paragraph, captions and buttons.
  3. Sort the sizes and divide each one by the size below it. If the results cluster around one number, such as 1.2 or 1.25, that is the ratio.
  4. Resize the window and check again. If the heading size changes smoothly, the site uses fluid type. If it jumps, it uses breakpoints.

Expect some noise. Many production scales are rounded to whole pixels or adjusted by hand, and some are not modular at all. A detailed walkthrough is in how to find font size and line height.

See every size a page uses in one list.

Fonts on this page lists each family with the weights and sizes it appears in, so you can read a site’s type scale without inspecting elements one by one.

Add to Chrome
Font Inspector’s Fonts on this page panel showing each font family with its share of text and the list of weights and sizes used on the page
The sizes listed under each family are the site’s type scale in practice.

With Font Inspector, open Fonts on this page. Each family is listed with the weights and sizes it is used at, and you can copy the list. Sort the sizes, divide neighbors, and you have the ratio. A long, irregular list is useful information too: it tells you the site has no scale, and shows what that looks like. To capture a single style exactly, click the text and copy it as CSS or Tailwind classes. The panel gives the size in px, em and rem. See how to see all fonts on a page for more on the page-wide view.

Questions & answers

What is a typography scale?+

It is a limited set of font sizes that share a common ratio, used consistently across a design. Each size is the previous one multiplied by the ratio, which makes the sizes look related and the hierarchy clear.

What is the best type scale ratio for a website?+

There is no single best ratio, but 1.2 to 1.333 suits most websites. Use a smaller ratio such as 1.125 or 1.2 for dense interfaces and phones, and a larger one such as 1.333 for editorial and marketing pages.

Should a type scale use px or rem?+

Use rem. One rem follows the browser’s default font size, so people who have increased their text size get a proportionally larger scale. Pixel values on the root element override that preference.

How do I make font sizes responsive with clamp()?+

Use font-size: clamp(min, preferred, max) where the preferred value combines rem and vw, for example clamp(2rem, 1.5rem + 2.5vw, 3.5rem). The rem part keeps the text responsive to user settings and zoom.

How many font sizes should a website have?+

Five to eight sizes cover most sites: one or two below body text, the body size, and four or five heading and display steps. If you need more, check whether weight, color or spacing could do the job.

Related free tools: Type scale calculator · PX to REM converter

Sources and further reading: MDN: clamp() · MDN: line-height · Tailwind CSS: font-size · W3C: Understanding Success Criterion 1.4.4 Resize Text

Line height and letter spacing: the invisible difference

How to set line height and letter spacing in CSS: unitless values, ranges for body and headings, line length, WCAG text spacing and how to inspect it.

How to pair fonts (without overthinking it)

A practical method for pairing fonts: give each typeface a job, pick one clear contrast, test on real content, and study pairings on sites you admire.

How to find the font size, weight and line height of any text

Read the exact font size, weight, line height and letter spacing of any text on a website, and convert the pixel values into rem, em and a ratio.