2026-09-19 · 7 min · By Alcott Dube
How to build a ui type scale that survives real content
I choose type sizes around actual interface content, then test line height, text width and wrapping before turning those decisions into reusable tokens.

I build an interface type scale by choosing a readable body size, adding a small set of role-based sizes, and setting line height and text width separately for each role. I keep the scale only if long labels, realistic paragraphs, narrow screens and enlarged text preserve both readability and hierarchy.
Choose a body text size before a scale ratio
I start with the text someone must read to complete a task: instructions, form descriptions or a record's details. For a browser-based product, 1rem is a useful first trial, usually 16px at the browser's default setting. That's a starting point, not proof of readability. The chosen font, its weight and the viewing conditions still matter.
I put a short instruction, a three-sentence explanation and a validation message beside each other in the actual typeface. A font with a small x-height can feel noticeably smaller than another at the same nominal size. I compare candidates at the same container width, rather than judging an isolated alphabet specimen.
I don't shrink the main reading size to rescue an overcrowded layout. First I remove duplicated information, shorten unnecessary copy or change the grouping. Dense tables may need a smaller supporting style, but that should be a deliberate exception. Making every sentence smaller transfers a layout problem to the reader.
Choose type scale steps that create useful differences
Once body text works, I try a compact sequence such as 12, 14, 16, 20, 24 and 32px. These are candidate sizes, not six styles that every screen must use. I reserve 12px for brief, nonessential metadata, if it survives testing. Instructions and error messages don't qualify merely because they're secondary.
A modular ratio can generate a first draft. Starting at 16px with a 1.25 multiplier produces 20, 25 and 31.25px. I might round those to 20, 24 and 32px because the resulting distinctions suit the interface better. Mathematical consistency isn't the objective. I want each step to make a recognisable contribution to hierarchy.
I test the sequence on one ordinary screen before adding more sizes. If 20px and 24px headings perform the same job, I remove one. If a section needs more separation, I try spacing or weight first. More sizes create more decisions for everyone maintaining the product, without necessarily making its structure clearer.

Turn font sizes into semantic typography tokens
Material Design groups typography into display, headline, title, body and label roles, with size variants. I use that distinction as a framework, not a requirement to reproduce its whole catalogue. An administrative product might need page titles, section titles, body text, labels and metadata. A display role may have no useful job there.
I name tokens after those jobs: page-title, section-title, body-default, field-label and metadata. Each definition includes font family, size, weight, line height and any intentional letter spacing. A size alone isn't a text style. Two elements set at 16px can behave quite differently when one is a paragraph and the other a compact control label.
I allow roles to share values. A field label and body text might both use 1rem while differing in weight and line height. That doesn't make either token redundant: their purposes can change independently. I document where each role belongs, including restrictions such as keeping metadata styling away from information required to finish a task.
Set line height for paragraphs, headings and labels
For 16px body text, I start with a unitless line height of 1.5, giving 24px at that size. I then read a paragraph that wraps across several lines. I look for comfortable tracking from one line to the next, without so much separation that each line feels detached. This needs checking in the selected font.
Headings usually need tighter proportions. I might test 32px text at 1.25, producing a 40px line box, and 24px text at roughly 1.33, producing about 32px. I always include a heading that wraps. A setting that looks tidy on a single line can crowd accents or make a two-line title difficult to scan.
For controls, I separate text line height from component height. A 20px line box inside a 44px button leaves room for vertical padding; the line box doesn't need to fill the button. I avoid fixed heights on containers that must accept wrapped labels or messages. Unitless line heights follow the element's font size, but the surrounding layout must still accommodate growth.
Choose a text measure that fits the reading task
Measure is the width of a text block. Smashing Magazine's discussion of responsive typography connects that width with font size and line spacing rather than treating them as separate choices. I follow the same principle: after changing a column width, I read its paragraphs again. A good setting in a narrow panel may feel tiring across a wide page.
For explanatory prose, I start around 45 to 75 characters per line, including spaces, then judge the actual result. I might use max-width: 65ch as an initial constraint. The ch unit follows the advance width of the font's zero character, so it doesn't guarantee 65 characters in a line. It's a practical control, not a precise count.
I don't impose that prose measure on navigation or table cells. Those need widths based on their content and task. I let a settings page remain wider than its introductory paragraph, rather than stretching the paragraph to match every field. Shared alignment can establish order without making all text blocks equally wide.
Adapt the type scale for narrow screens and zoom
I keep ordinary body text relatively stable across screen sizes. On a narrow screen, I usually reduce a large page title before reducing reading text. A 32px title might become 28px while body text stays at 1rem. I also adjust gutters and spacing, because type size alone can't repair a cramped composition.
Fluid sizing can help a prominent heading, but I bound it carefully and include a relative component rather than relying entirely on viewport units. I don't make every label and paragraph fluid. Small, continuous changes are harder to inspect and can alter wrapping throughout a form for little practical benefit.
I check the layout at narrow widths and with browser zoom at 200%, then test text enlargement separately where supported. I look for clipped messages, overlapping labels and controls that hide their contents. These checks aren't a complete accessibility audit. They are useful ways to expose assumptions about how much space text will occupy.
Test real content before publishing typography tokens
I build a small stress-test page with a normal record and a deliberately awkward one. The awkward version includes a long organisation name, a two-line button label, an unbroken identifier, an empty state and a validation message with a recovery instruction. If localisation is planned, I include representative translated content rather than assuming English sets the maximum length.
I inspect four things: hierarchy, wrapping, clipping and reading comfort. I record where a title overwhelms the content, where a label becomes ambiguous after truncation, and where a paragraph needs a narrower measure. I don't use fewer line breaks as a universal success metric. An extra line can be the correct cost of readable text.
I fix failures in order: content, available width, component behaviour, then typography. Shortening a redundant label is better than inventing a special 13px style for it. Before publishing tokens, I record the tested font, intended roles and known exceptions. I also check the fallback font, since loading delays can expose different widths before the preferred face appears.
Questions people ask
What is the best ratio for a ui type scale?
I usually test a modest ratio such as 1.2 or 1.25, then adjust the generated sizes to fit the interface. I don't preserve a ratio when it creates indistinguishable roles or oversized headings.
How many font sizes should an interface use?
I start with about five or six sizes, and many individual screens need fewer. I add another only when an existing size, weight or spacing choice can't express a necessary distinction.
What line height should I use for 16px text?
I start paragraph text at 1.5, which gives a 24px line box. I check several wrapped lines in the actual font before adjusting it; compact labels may need a different setting.
Should I use rem or px for a type scale?
For web interfaces, I generally use rem for font sizes and unitless values for line height. I leave the root size responsive to browser preferences and test enlargement rather than assuming the units guarantee accessibility.