Typography System Guide for iOS and Android

Comprehensive guide for implementing accessible typography in mobile apps – (V 1.2)

iOS Typography System

Apple's San Francisco font family with Dynamic Type support for accessibility. Automatically switches between SF Pro Text for smaller sizes (≤19pt) and SF Pro Display for larger sizes (≥20pt).

iOS Default Typography Styles

Large Title
Font SF Pro Display
Weight Bold
Size 34pt
Line Height 41pt
Title 1
Font SF Pro Display
Weight Regular
Size 28pt
Line Height 34pt
Title 2
Font SF Pro Display
Weight Regular
Size 22pt
Line Height 28pt
Title 3
Font SF Pro Display
Weight Regular
Size 20pt
Line Height 25pt
Headline
Font SF Pro Text
Weight Semibold
Size 17pt
Line Height 22pt
Body
Font SF Pro Text
Weight Regular
Size 17pt
Line Height 22pt
Callout
Font SF Pro Text
Weight Regular
Size 16pt
Line Height 21pt
Subhead
Font SF Pro Text
Weight Regular
Size 15pt
Line Height 20pt
Footnote
Font SF Pro Text
Weight Regular
Size 13pt
Line Height 18pt
Caption 1
Font SF Pro Text
Weight Regular
Size 12pt
Line Height 16pt
Caption 2
Font SF Pro Text
Weight Regular
Size 11pt
Line Height 13pt

Dynamic Type Demo

Large (Default)
Large Title The quick brown fox
Title 1 The quick brown fox
Title 2 The quick brown fox
Headline The quick brown fox
Body The quick brown fox
Callout The quick brown fox
Footnote The quick brown fox
Caption 1 The quick brown fox

Implementation Guidelines for iOS

Here are the best practices to properly implement typography in iOS applications:

  • Use San Francisco font for a native iOS look and feel
  • Implement Dynamic Type for accessibility compliance
  • Set minimum font size for body text to 17pt for readability
  • For custom fonts, use UIFontMetrics for Dynamic Type
  • Test your app with all Dynamic Type size settings
// Swift code for Dynamic Type with system font
label.font = UIFont.preferredFont(forTextStyle: .body)
label.adjustsFontForContentSizeCategory = true

// With custom font
let customFont = UIFont(name: "CustomFont-Regular", size: 16)!
label.font = UIFontMetrics.default.scaledFont(for: customFont)
label.adjustsFontForContentSizeCategory = true

Android Typography System

Android uses the Roboto font family in Material Design. Text sizes in "sp" automatically scale with user preferences.

Android Material Typography Styles

Display Large
Font Roboto
Weight Regular
Size 57sp
Line Height 64sp
Display Medium
Font Roboto
Weight Regular
Size 45sp
Line Height 52sp
Display Small
Font Roboto
Weight Regular
Size 36sp
Line Height 44sp
Headline Large
Font Roboto
Weight Regular
Size 32sp
Line Height 40sp
Headline Medium
Font Roboto
Weight Regular
Size 28sp
Line Height 36sp
Headline Small
Font Roboto
Weight Regular
Size 24sp
Line Height 32sp
Title Large
Font Roboto
Weight Regular
Size 22sp
Line Height 28sp
Title Medium
Font Roboto
Weight Medium
Size 16sp
Line Height 24sp
Title Small
Font Roboto
Weight Medium
Size 14sp
Line Height 20sp
Body Large
Font Roboto
Weight Regular
Size 16sp
Line Height 24sp
Body Medium
Font Roboto
Weight Regular
Size 14sp
Line Height 20sp
Body Small
Font Roboto
Weight Regular
Size 12sp
Line Height 16sp
Label Large
Font Roboto
Weight Medium
Size 14sp
Line Height 20sp
Label Medium
Font Roboto
Weight Medium
Size 12sp
Line Height 16sp
Label Small
Font Roboto
Weight Medium
Size 11sp
Line Height 16sp

Font Scaling Demo

1x
Display Large The quick brown fox
Headline Large The quick brown fox
Title Medium The quick brown fox
Body Large The quick brown fox
Label Small The quick brown fox

Implementation Guidelines for Android

Here are the best practices to properly implement typography in Android applications:

  • Always define text sizes in scalable pixels (sp) to respect user font size preferences
  • The minimum recommended size for body text is 16sp for readability
  • For dense lists or information, you can use 14sp with a slightly heavier weight
  • Use dynamic layouts with wrap_content and constraintLayout to adapt to different text sizes
  • Test your app with font scaling set to at least 1.3x to ensure layout adaptability
<!-- XML layout example -->
<TextView
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:textSize="16sp"
   android:textColor="@color/textPrimary"
   android:text="@string/sample_text" />

<!-- Compose example -->
Text(
   text = "Sample Text",
   style = MaterialTheme.typography.bodyLarge,
   modifier = Modifier.fillMaxWidth()
)

Typography Accessibility Guidelines

Creating accessible typography following WCAG 2.1 AA standards for text scaling and readability.

WCAG 2.1 Success Criterion 1.4.4 - Resize Text

Requirement

Level AA

Text can be resized without assistive technology up to 200% without loss of content or functionality.

Mobile Implementation

  • Respect OS text size preferences
  • Use Dynamic Type (iOS) and sp units (Android)
  • Maintain functionality at all text sizes
  • Avoid horizontal scrolling

Assistive Technology vs. Accessibility Features

✅ Acceptable (Accessibility Features)

  • iOS: Dynamic Type size adjustments in Settings
  • Android: Font size scaling in Display settings
  • Both: Bold text system preferences
  • WebViews: Built-in browser zoom functionality

⚠️ Not Sufficient Alone (Assistive Technology)

  • iOS: Magnifier or 3-finger zoom
  • Android: Magnification gestures
  • Both: External screen reader zoom features

Note: While these are valuable, they should supplement, not replace, proper text scaling support.

Implementation Requirements for WCAG 1.4.4 Compliance

1. Implement Native Text Scaling

Use platform-specific APIs to ensure text scales with system settings:

// iOS - UIKit
label.font = UIFont.preferredFont(forTextStyle: .body)
label.adjustsFontForContentSizeCategory = true

// iOS - SwiftUI
Text("Sample Text")
    .font(.body)
    .dynamicTypeSize(.large ... .accessibility5)
<!-- Android XML -->
<TextView
    android:textSize="16sp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

// Android Compose
Text(
    text = "Sample Text",
    style = MaterialTheme.typography.bodyLarge
)
2. Responsive Layout Design

Ensure layouts adapt to larger text without breaking:

// iOS - Auto Layout
stackView.axis = .vertical
stackView.spacing = 8
label.numberOfLines = 0

// SwiftUI
VStack(spacing: 8) {
    Text("Title")
        .lineLimit(nil)
}
<!-- Android ConstraintLayout -->
<androidx.constraintlayout.widget.ConstraintLayout>
    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintWidth_percent="0.8" />
</androidx.constraintlayout.widget.ConstraintLayout>
3. Handle Dynamic Changes

Respond to font size changes at runtime:

// iOS - Notification handling
NotificationCenter.default.addObserver(
    self,
    selector: #selector(contentSizeCategoryDidChange),
    name: UIContentSizeCategory.didChangeNotification,
    object: nil
)
// Android - Configuration changes
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    // Refresh UI to reflect new font scale
    recreateViews()
}

Understanding Non-Linear Text Scaling

Both iOS and Android use non-linear scaling curves, meaning different text styles scale at different rates to maintain readability.

iOS Non-Linear Scaling to Accessibility Sizes
Text Style Default (Large) AX5 (Largest) Scale Factor Reaches 200%?
Large Title 34pt 76pt 2.24x (224%) ✅ Yes
Title 1 28pt 60pt 2.14x (214%) ✅ Yes
Body 17pt 53pt 3.12x (312%) ✅ Yes
Caption 1 12pt 38pt 3.17x (317%) ✅ Yes
Android Non-Linear Scaling Behavior
Base Size Default (1.0x) Largest (1.3x setting) Actual Scale Factor Reaches 200%?
8sp 8sp 16sp 2.0x (200%) ✅ Yes
12sp 12sp 24sp 2.0x (200%) ✅ Yes
14sp 14sp 26sp 1.86x (186%) ⚠️ Close
16sp 16sp 28sp 1.75x (175%) ❌ No
18sp 18sp 30sp 1.67x (167%) ❌ No
Key Insight

Android text larger than 14sp may not reach the 200% scaling threshold. However, this is still considered compliant as the platform provides the maximum scaling available to users.

Testing for WCAG 1.4.4 Compliance

Complete Testing Process

Step 1: Platform Setup
📱 iOS Setup
  1. Open SettingsAccessibility
  2. Tap Display & Text Size
  3. Select Larger Text
  4. Enable Larger Accessibility Sizes
  5. Test all sizes from XS to AX5
🤖 Android Setup
  1. Open SettingsDisplay
  2. Tap Font size and style
  3. Test all sizes (Small to Huge)
  4. For extreme testing, use ADB:
    adb shell settings put system font_scale 2.0
Step 2: Validation Criteria
✅ Pass Requirements
  • All text scales using OS accessibility features
  • Content remains accessible at all sizes
  • No functionality lost when text enlarged
  • No horizontal scrolling required
  • Interactive elements remain usable
Step 3: Common Issues Checklist
🔍 Layout Issues
  • Fixed containers: Text overflow in fixed-height containers
  • Overlapping elements: Scaled text overlaps other UI elements
  • Cut-off text: Text clipped in constrained spaces
🎯 Interaction Issues
  • Button labels: Action buttons become unusable if text doesn't fit
  • Navigation: Tab bars and menus lose functionality
  • Form inputs: Labels and inputs misalign or overlap
Step 4: Documentation
  • 📋 Record test results for each text size
  • 📸 Screenshot any layout issues
  • 📝 Document workarounds for identified problems
  • ✅ Create compliance checklist for future releases

Testing Checklist

iOS Testing
Android Testing

Best Practices

Design

  • Plan for 200%+ text scaling
  • Use minimum 16sp/17pt for body text
  • Ensure WCAG AA color contrast
  • Design flexible layouts

Development

  • Implement Dynamic Type/sp units
  • Use flexible layout systems
  • Test with max accessibility settings
  • Handle font size notifications

Testing

  • Test with real users
  • Use accessibility testing tools
  • Verify all functionality works
  • Document any limitations

W3C MATF Recommendations Implementation

Based on the ongoing W3C Mobile Accessibility Task Force (MATF) discussions, this guide implements:

  • Clear AT vs. Accessibility Feature distinction: We differentiate between zoom (assistive technology) and text scaling (accessibility feature)
  • Non-linear scaling documentation: We provide actual scaling data from both platforms
  • Platform-specific requirements: We detail what each OS requires for compliance
  • WebView considerations: We address the complexities of web content in native apps
  • Testing methodologies: We provide concrete testing steps for validation