Guideline 4.0
Guideline 4.0 - Design: Dynamic Type and Large Text Not Supported
Our Take
Apple rejected your app because it does not respect the user's Dynamic Type preferences. When users increase their preferred text size in Settings → Accessibility → Display & Text Size, your app's text does not scale accordingly. This results in text that remains too small for users who need larger text, or layouts that break, truncate, or overlap when large text sizes are enabled. Apple expects all apps to support Dynamic Type for body text, labels, and buttons.
Resolution Guide
**Replace hardcoded font sizes with text styles** — In SwiftUI, use semantic font modifiers instead of `.system(size:)`:
```swift
// Before: .font(.system(size: 14))
// After:
.font(.body) // 17pt default, scales with Dynamic Type
.font(.headline) // 17pt bold, scales
.font(.caption) // 12pt, scales
```
In UIKit, use `UIFont.preferredFont(forTextStyle:)`.
**Use @ScaledMetric for custom sizes** — When you need a specific size that still scales:
```swift
@ScaledMetric(relativeTo: .body) private var iconSize: CGFloat = 24
Image(systemName: "star")
.frame(width: iconSize, height: iconSize)
```
**Enable text wrapping, not truncation** — Ensure labels can expand vertically at large sizes:
```swift
Text("Long label text")
.lineLimit(nil) // allow unlimited lines
.fixedSize(horizontal: false, vertical: true) // grow vertically
```
In UIKit, set `label.numberOfLines = 0` and `label.adjustsFontForContentSizeCategory = true`.
**Adapt layouts for large text** — At accessibility sizes, horizontal layouts may need to become vertical. Use `@Environment(\.dynamicTypeSize)` to switch:
```swift
@Environment(\.dynamicTypeSize) var typeSize
if typeSize.isAccessibilitySize {
VStack { labelContent; valueContent }
} else {
HStack { labelContent; Spacer(); valueContent }
}
```
**Ensure scroll views accommodate large text** — Wrap content in ScrollView so that screens with lots of text remain usable at the largest sizes rather than clipping at the bottom.
**Test at all 12 Dynamic Type sizes** — In the iOS Simulator, use the Environment Overrides panel (Debug → Environment Overrides) to test at every size from xSmall to AX5. Pay special attention to AX1–AX5 (accessibility sizes) where most breakage occurs.
**Use Accessibility Inspector** — Xcode's Accessibility Inspector can audit your app for Dynamic Type support issues and highlight elements that don't scale.
Example Rejection Email
Consider Appealing
Do not appeal this rejection. Dynamic Type support is an accessibility requirement that Apple takes seriously. The fix may take a few hours but is well worth it — it benefits users with low vision and is the right thing to do. If you've already added Dynamic Type support and the reviewer missed it, provide screenshots at the largest text size in your Resolution Center reply.
Before & After
// Hardcoded sizes — no Dynamic Type support
VStack(alignment: .leading, spacing: 8) {
Text(item.title)
.font(.system(size: 16, weight: .bold))
Text(item.subtitle)
.font(.system(size: 14))
.lineLimit(1)
HStack {
Image(systemName: "star")
.frame(width: 16, height: 16)
Text(item.rating)
.font(.system(size: 12))
}
}
// Dynamic Type with adaptive layout
@ScaledMetric(relativeTo: .caption) private var starSize: CGFloat = 16
VStack(alignment: .leading, spacing: 8) {
Text(item.title)
.font(.headline)
Text(item.subtitle)
.font(.subheadline)
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
HStack {
Image(systemName: "star")
.frame(width: starSize, height: starSize)
Text(item.rating)
.font(.caption)
}
}
What changed: Replace .system(size:) with semantic text styles (.headline, .subheadline, .caption) that scale automatically with Dynamic Type. Use @ScaledMetric for icon sizes so they grow proportionally. Remove lineLimit(1) to allow text to wrap at large sizes.
// Fixed horizontal layout that breaks at large text
HStack {
Text("Balance:")
.font(.system(size: 14))
Spacer()
Text("$1,234.56")
.font(.system(size: 14, weight: .bold))
}
// Adaptive layout that stacks vertically at accessibility sizes
@Environment(\.dynamicTypeSize) var typeSize
Group {
if typeSize.isAccessibilitySize {
VStack(alignment: .leading, spacing: 4) {
Text("Balance:")
.font(.subheadline)
Text("$1,234.56")
.font(.headline)
}
} else {
HStack {
Text("Balance:")
.font(.subheadline)
Spacer()
Text("$1,234.56")
.font(.headline)
}
}
}
What changed: At accessibility text sizes, horizontal space is too limited for side-by-side labels. Use @Environment(\.dynamicTypeSize) to detect large sizes and switch to a vertical layout, preventing truncation and overlap.
Community Solutions · 0
Sign in to share your solution.
More Guideline 4 (Design) rejections
- Guideline 4.0 - Design: App Does Not Include iOS Features
- Guideline 4.0 - Design: App Looks Like a Website
- Guideline 4.0 - Design: Apple Pay Button Not Following Guidelines
- Guideline 4.0 - Design: Blurry Icons or Low-Resolution Assets
- Guideline 4.0 - Design: Broken Layout on iPad
- Guideline 4.0 - Design: Content Clipped by Notch or Safe Area