Mobile Typography Reference
Type scale, system fonts, Dynamic Type, accessibility, and dark mode typography.
Typography failures are the #1 cause of unreadable mobile apps.
1. Mobile Typography Fundamentals
Why Mobile Type is Different
DESKTOP: MOBILE:
├── 20-30" viewing distance ├── 12-15" viewing distance
├── Large viewport ├── Small viewport, narrow
├── Hover for details ├── Tap/scroll for details
├── Controlled lighting ├── Variable (outdoor, etc.)
├── Fixed font size ├── User-controlled sizing
└── Long reading sessions └── Quick scanning
Mobile Type Rules
| Rule |
Desktop |
Mobile |
| Minimum body size |
14px |
16px (14pt/14sp) |
| Maximum line length |
75 characters |
40-60 characters |
| Line height |
1.4-1.5 |
1.4-1.6 (more generous) |
| Font weight |
Varies |
Regular dominant, bold sparingly |
| Contrast |
AA (4.5:1) |
AA minimum, AAA preferred |
2. System Fonts
iOS: SF Pro Family
San Francisco (SF) Family:
├── SF Pro Display: Large text (≥ 20pt)
├── SF Pro Text: Body text (< 20pt)
├── SF Pro Rounded: Friendly contexts
├── SF Mono: Monospace
└── SF Compact: Apple Watch, compact UI
Features:
├── Optical sizing (auto-adjusts)
├── Dynamic tracking (spacing)
├── Tabular/proportional figures
├── Excellent legibility
Android: Roboto Family
Roboto Family:
├── Roboto: Default sans-serif
├── Roboto Flex: Variable font
├── Roboto Serif: Serif option
├── Roboto Mono: Monospace
├── Roboto Condensed: Narrow spaces
Features:
├── Optimized for screens
├── Wide language support
├── Multiple weights
├── Good at small sizes
When to Use System Fonts
✅ USE system fonts when:
├── Brand doesn't mandate custom font
├── Reading efficiency is priority
├── App feels native/integrated important
├── Performance is critical
├── Wide language support needed
❌ AVOID system fonts when:
├── Brand identity requires custom
├── Design differentiation needed
├── Editorial/magazine style
└── (But still support accessibility)
Custom Font Considerations
If using custom fonts:
├── Include all weights needed
├── Subset for file size
├── Test at all Dynamic Type sizes
├── Provide fallback to system
├── Test rendering quality
└── Check language support
3. Type Scale
iOS Type Scale (Built-in)
| Style |
Size |
Weight |
Line Height |
| Large Title |
34pt |
Bold |
41pt |
| Title 1 |
28pt |
Bold |
34pt |
| Title 2 |
22pt |
Bold |
28pt |
| Title 3 |
20pt |
Semibold |
25pt |
| Headline |
17pt |
Semibold |
22pt |
| Body |
17pt |
Regular |
22pt |
| Callout |
16pt |
Regular |
21pt |
| Subhead |
15pt |
Regular |
20pt |
| Footnote |
13pt |
Regular |
18pt |
| Caption 1 |
12pt |
Regular |
16pt |
| Caption 2 |
11pt |
Regular |
13pt |
Android Type Scale (Material 3)
| Role |
Size |
Weight |
Line Height |
| Display Large |
57sp |
400 |
64sp |
| Display Medium |
45sp |
400 |
52sp |
| Display Small |
36sp |
400 |
44sp |
| Headline Large |
32sp |
400 |
40sp |
| Headline Medium |
28sp |
400 |
36sp |
| Headline Small |
24sp |
400 |
32sp |
| Title Large |
22sp |
400 |
28sp |
| Title Medium |
16sp |
500 |
24sp |
| Title Small |
14sp |
500 |
20sp |
| Body Large |
16sp |
400 |
24sp |
| Body Medium |
14sp |
400 |
20sp |
| Body Small |
12sp |
400 |
16sp |
| Label Large |
14sp |
500 |
20sp |
| Label Medium |
12sp |
500 |
16sp |
| Label Small |
11sp |
500 |
16sp |
Creating Custom Scale
If creating custom scale, use modular ratio:
Recommended ratios:
├── 1.125 (Major second): Dense UI
├── 1.200 (Minor third): Compact
├── 1.250 (Major third): Balanced (common)
├── 1.333 (Perfect fourth): Spacious
└── 1.500 (Perfect fifth): Dramatic
Example with 1.25 ratio, 16px base:
├── xs: 10px (16 ÷ 1.25 ÷ 1.25)
├── sm: 13px (16 ÷ 1.25)
├── base: 16px
├── lg: 20px (16 × 1.25)
├── xl: 25px (16 × 1.25 × 1.25)
├── 2xl: 31px
├── 3xl: 39px
└── 4xl: 49px
4. Dynamic Type / Text Scaling
iOS Dynamic Type (MANDATORY)
// ❌ WRONG: Fixed size (doesn't scale)
Text("Hello")
.font(.system(size: 17))
// ✅ CORRECT: Dynamic Type
Text("Hello")
.font(.body) // Scales with user setting
// Custom font with scaling
Text("Hello")
.font(.custom("MyFont", size: 17, relativeTo: .body))
Android Text Scaling (MANDATORY)
ALWAYS use sp for text:
├── sp = Scale-independent pixels
├── Scales with user font preference
├── dp does NOT scale (don't use for text)
User can scale from 85% to 200%:
├── Default (100%): 14sp = 14dp
├── Largest (200%): 14sp = 28dp
Test at 200%!
Scaling Challenges
Problems at large text sizes:
├── Text overflows containers
├── Buttons become too tall
├── Icons look small relative to text
├── Layouts break
Solutions:
├── Use flexible containers (not fixed height)
├── Allow text wrapping
├── Scale icons with text
├── Test at extremes during development
├── Use scrollable containers for long text
5. Typography Accessibility
Minimum Sizes
| Element |
Minimum |
Recommended |
| Body text |
14px/pt/sp |
16px/pt/sp |
| Secondary text |
12px/pt/sp |
13-14px/pt/sp |
| Captions |
11px/pt/sp |
12px/pt/sp |
| Buttons |
14px/pt/sp |
14-16px/pt/sp |
| Nothing smaller |
11px |
- |
Contrast Requirements (WCAG)
Normal text (< 18pt or < 14pt bold):
├── AA: 4.5:1 ratio minimum
├── AAA: 7:1 ratio recommended
Large text (≥ 18pt or ≥ 14pt bold):
├── AA: 3:1 ratio minimum
├── AAA: 4.5:1 ratio recommended
Logos/decorative: No requirement
Line Height for Accessibility
WCAG Success Criterion 1.4.12:
Line height (line spacing): ≥ 1.5×
Paragraph spacing: ≥ 2× font size
Letter spacing: ≥ 0.12× font size
Word spacing: ≥ 0.16× font size
Mobile recommendation:
├── Body: 1.4-1.6 line height
├── Headings: 1.2-1.3 line height
├── Never below 1.2
6. Dark Mode Typography
Color Adjustments
Light Mode: Dark Mode:
├── Black text (#000) ├── White/light gray (#E0E0E0)
├── High contrast ├── Slightly reduced contrast
├── Full saturation ├── Desaturated colors
└── Dark = emphasis └── Light = emphasis
RULE: Don't use pure white (#FFF) on dark.
Use off-white (#E0E0E0 to #F0F0F0) to reduce eye strain.
Dark Mode Hierarchy
| Level |
Light Mode |
Dark Mode |
| Primary text |
#000000 |
#E8E8E8 |
| Secondary text |
#666666 |
#A0A0A0 |
| Tertiary text |
#999999 |
#707070 |
| Disabled text |
#CCCCCC |
#505050 |
Weight in Dark Mode
Dark mode text appears thinner due to halation
(light bleeding into dark background)
Consider:
├── Using medium weight for body (instead of regular)
├── Increasing letter-spacing slightly
├── Testing on actual OLED displays
└── Using slightly bolder weight than light mode
7. Typography Anti-Patterns
❌ Common Mistakes
| Mistake |
Problem |
Fix |
| Fixed font sizes |
Ignores accessibility |
Use dynamic sizing |
| Too small text |
Unreadable |
Min 14pt/sp |
| Low contrast |
Invisible in sunlight |
Min 4.5:1 |
| Long lines |
Hard to track |
Max 60 chars |
| Tight line height |
Cramped, hard to read |
Min 1.4× |
| Too many sizes |
Visual chaos |
Max 5-7 sizes |
| All caps body |
Hard to read |
Headlines only |
| Light gray on white |
Impossible in bright light |
Higher contrast |
❌ AI Typography Mistakes
AI tends to:
├── Use fixed px values instead of pt/sp
├── Skip Dynamic Type support
├── Use too small text (12-14px body)
├── Ignore line height settings
├── Use low contrast "aesthetic" grays
├── Apply same scale to mobile as desktop
└── Skip testing at large text sizes
RULE: Typography must SCALE.
Test at smallest and largest settings.
8. Font Loading & Performance
Font File Optimization
Font file sizes matter on mobile:
├── Full font: 100-300KB per weight
├── Subset (Latin): 15-40KB per weight
├── Variable font: 100-200KB (all weights)
Recommendations:
├── Subset to needed characters
├── Use WOFF2 format
├── Max 2-3 font files
├── Consider variable fonts
├── Cache fonts appropriately
Loading Strategy
1. SYSTEM FONT FALLBACK
Show system font → swap when custom loads
2. FONT DISPLAY SWAP
font-display: swap (CSS)
3. PRELOAD CRITICAL FONTS
Preload fonts needed above the fold
4. DON'T BLOCK RENDER
Don't wait for fonts to show content
9. Typography Checklist
Before Any Text Design
Before Release
10. Quick Reference
Typography Tokens
// iOS
.largeTitle // 34pt, Bold
.title // 28pt, Bold
.title2 // 22pt, Bold
.title3 // 20pt, Semibold
.headline // 17pt, Semibold
.body // 17pt, Regular
.subheadline // 15pt, Regular
.footnote // 13pt, Regular
.caption // 12pt, Regular
// Android (Material 3)
displayLarge // 57sp
headlineLarge // 32sp
titleLarge // 22sp
bodyLarge // 16sp
labelLarge // 14sp
Minimum Sizes
Body: 14-16pt/sp (16 preferred)
Secondary: 12-13pt/sp
Caption: 11-12pt/sp
Nothing: < 11pt/sp
Line Height
Headings: 1.1-1.3
Body: 1.4-1.6
Long text: 1.5-1.75
Remember: If users can't read your text, your app is broken. Typography isn't decoration—it's the primary interface. Test on real devices, in real conditions, with accessibility settings enabled.