Typography in UI: Best Practices for Web and Mobile
Typography Makes or Breaks Your UI#
If you stripped all color, imagery, and decorative elements from any digital product, the typography alone would determine whether it feels professional or amateur. Type is the primary vehicle for information in most interfaces — get it right, and everything else falls into place.
Choosing a Typeface#
For UI design, readability at small sizes trumps everything. Here's what to look for:
Must-have qualities#
- Large x-height — the height of lowercase letters relative to capitals. Larger x-height = better legibility at small sizes
- Open apertures — the openings in letters like 'c', 'e', 'a'. More open = easier to distinguish at a glance
- Distinct letterforms — can you easily tell apart
Il1(uppercase I, lowercase l, number 1)? What aboutO0(letter O, number 0)? - Complete character set — does it support the languages your product needs?
Reliable choices for product UI#
| Typeface | Style | Why it works |
|---|---|---|
| Inter | Neo-grotesque | Purpose-built for screens, massive character set |
| SF Pro | Humanist | Native to Apple platforms, optical sizes |
| Roboto | Neo-grotesque | Google's system font, excellent for Android |
| IBM Plex Sans | Humanist | Open source, technical yet warm |
| Geist | Geometric | Excellent for developer tools and dashboards |
| Source Sans 3 | Humanist | Adobe's open-source workhorse |
Font Count
One typeface is enough for most products. Two is the maximum for interfaces (one for UI, one for marketing/display). Three or more creates visual noise — each additional font adds cognitive load and file size.
Building a Type Scale#
A type scale is a set of predefined font sizes that creates visual hierarchy. Using arbitrary sizes ("this feels like 17px") creates inconsistency. A mathematical scale creates harmony.
Popular scale ratios#
| Ratio | Name | Best for |
|---|---|---|
| 1.125 | Major Second | Dense UIs, dashboards |
| 1.200 | Minor Third | General-purpose products |
| 1.250 | Major Third | Content-heavy sites, blogs |
| 1.333 | Perfect Fourth | Marketing, editorial |
| 1.500 | Perfect Fifth | Bold, statement typography |
Example scale (1.25 ratio, 16px base)#
xs: 12px → Captions, labels, timestamps
sm: 14px → Secondary text, metadata
base: 16px → Body text (the anchor)
lg: 20px → Lead paragraphs, large body
xl: 24px → H4, section subheadings
2xl: 30px → H3
3xl: 38px → H2
4xl: 48px → H1, page titles
5xl: 60px → Display, hero headlines
Every text element in your UI should use one of these sizes. No exceptions, no "just this once."
Line Height: The Invisible Backbone#
Line height (or leading) is the vertical space between lines of text. Too tight and text feels cramped; too loose and the eye loses track of the next line.
Rules of thumb#
- Body text (14-18px): line height of 1.5-1.6× the font size
- Headings (24px+): line height of 1.2-1.3×
- Large display text (48px+): line height of 1.0-1.15×
- Tight UI elements (labels, buttons): line height of 1.2-1.4×
The pattern: larger text needs proportionally less line height. A 60px heading with 1.6× line height would have enormous gaps between lines.
Line height for readability#
For long-form content (articles, documentation), err on the generous side:
.body-text {
font-size: 16px;
line-height: 1.625; /* 26px — comfortable for reading */
}
For compact UI elements (table cells, navigation, badges), tighten it up:
.ui-label {
font-size: 14px;
line-height: 1.286; /* 18px — space-efficient */
}
Measure: The Optimal Line Length#
The "measure" is the width of a text block, typically counted in characters. Research consistently shows:
- Optimal: 45-75 characters per line
- Ideal: around 66 characters
- Mobile: 35-50 characters (due to smaller screens)
Lines that are too long cause the eye to lose its place when returning to the left margin. Lines too short create excessive hyphenation and constant line breaks.
.article-body {
max-width: 680px; /* roughly 65-70 characters at 16px */
}
Quick Test
Count the characters in one line of your body text. If you're consistently above 80 or below 40, adjust the container width. This single change can dramatically improve readability.
Font Weight as Hierarchy#
Don't rely on size alone for hierarchy. Weight is a powerful secondary differentiator:
| Element | Weight | Size | Purpose |
|---|---|---|---|
| Page title | Bold (700) | 4xl | Unmissable anchor |
| Section heading | Semibold (600) | 2xl | Structural division |
| Card title | Medium (500) | lg | Content grouping |
| Body text | Regular (400) | base | Reading comfort |
| Caption/meta | Regular (400) | sm | De-emphasized info |
| Label | Medium (500) | sm | Compact identification |
Notice: you only need 3-4 weights (400, 500, 600, 700). Using more creates ambiguity — is 300 or 400 the "normal" weight? Keep it simple.
Responsive Typography#
Text that looks perfect on desktop often breaks on mobile. Here are strategies that work:
Fluid type with clamp()#
CSS clamp() lets you set a minimum, preferred, and maximum font size that scales smoothly with viewport width:
h1 {
font-size: clamp(28px, 4vw + 1rem, 48px);
}
This means: never smaller than 28px, scale with viewport, never larger than 48px. No media query breakpoints needed.
Reduce the scale on mobile#
Desktop can handle dramatic size differences (12px caption to 60px hero). Mobile can't — the range should compress:
| Element | Desktop | Mobile |
|---|---|---|
| H1 | 48px | 28px |
| H2 | 30px | 22px |
| Body | 16px | 16px |
| Caption | 12px | 12px |
Notice that body and caption stay the same — you should never shrink body text below 16px on mobile. Readability is non-negotiable.
Font Loading Performance#
Beautiful typography means nothing if it causes layout shifts and slow load times.
Best practices#
- Self-host fonts — don't rely on Google Fonts CDN (extra DNS lookup, privacy concerns, potential blocking in some regions)
- Use
font-display: swap— shows fallback text immediately, swaps to custom font when loaded - Subset your fonts — if you only need Latin characters, don't load Cyrillic, Greek, and Vietnamese glyphs
- Preload critical fonts — add
<link rel="preload">for the font files used above the fold - Use variable fonts — one file replaces multiple weight/style files, reducing total download size
<link rel="preload" href="/fonts/inter-var.woff2"
as="font" type="font/woff2" crossorigin />
Performance Budget
Aim for under 100KB total font payload. A single variable font file (like Inter at ~100KB) replaces 4-6 static files that would total 300KB+. Variable fonts are almost always the better choice for performance.
Common Typography Mistakes#
1. Using too many sizes#
If you have more than 8-10 distinct font sizes in your product, you don't have a system — you have chaos. Audit and consolidate.
2. Centering long text#
Center alignment works for headings and short labels. For paragraphs longer than 2 lines, always use left alignment (or right for RTL languages). Centered paragraphs create a ragged left edge that's hard to scan.
3. Low contrast text#
Light gray text on white might look minimal, but it fails accessibility and frustrates users. Body text should have at least 4.5:1 contrast ratio against its background.
4. Ignoring the fold#
The first screen a user sees should establish the typographic hierarchy instantly. If a user can't distinguish the page title from body text at a glance, your hierarchy has failed.
5. Forgetting line length on wide screens#
On a 2560px-wide monitor with no max-width constraint, body text can stretch to 200+ characters per line — completely unreadable. Always constrain your text containers.
A Typography Checklist#
Before shipping any page, verify:
- All text uses sizes from the type scale (no custom values)
- Body text is 16px minimum on all devices
- Line height is set for every text style (not using browser defaults)
- Maximum line length is 75 characters or fewer
- Contrast ratios pass WCAG AA (4.5:1 for normal text)
- Fonts are self-hosted and preloaded
- No more than 2 typefaces are used
- Heading hierarchy is semantic (h1 → h2 → h3, not random)
- Text scales gracefully from 320px to 2560px viewport width
The Bottom Line#
Great typography is invisible — users don't notice it, they just read faster, understand better, and trust your product more. Bad typography is immediately obvious, even to people who can't articulate why something "feels off."
Invest in your type scale, enforce it ruthlessly, and treat text as the most important element in your interface. Because it is.
For tools that help streamline your design workflow, check out our Figma plugins — so you can spend more time on the craft that matters.