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
Dynamic Type Demo
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
Font Scaling Demo
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 AAText 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.
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 |
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
- Open Settings → Accessibility
- Tap Display & Text Size
- Select Larger Text
- Enable Larger Accessibility Sizes
- Test all sizes from XS to AX5
🤖 Android Setup
- Open Settings → Display
- Tap Font size and style
- Test all sizes (Small to Huge)
- 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