Fonts define the visual structure and readability of text in a SwiftUI interface. SwiftUI provides a typography system that adapts automatically to user settings, supports accessibility, and maintains consistency across Apple platforms.
This blog describes how to use system font styles, apply font modifiers, and integrate custom fonts in SwiftUI.
Fonts influence how users scan, read, and understand information in your app.
Good typography helps with:
SwiftUI encourages the use of semantic font styles instead of fixed font sizes. Semantic styles adapt to:
System font styles describe the purpose of text rather than its size. SwiftUI adjusts the actual font size automatically.
VStack(spacing: 12) {
Text("Large Title")
.font(.largeTitle)
Text("Title")
.font(.title)
Text("Title 2")
.font(.title2) //available in iOS 14 and onwards
Text("Title 3")
.font(.title3) //available in iOS 14 and onwards
Text("Headline")
.font(.headline)
Text("Sub Headline")
.font(.subheadline)
Text("Body")
.font(.body) // default
Text("Callout")
.font(.callout)
Text("Footnote")
.font(.footnote)
Text("Caption")
.font(.caption)
Text("Caption 2")
.font(.caption2) //available in iOS 14 and onwards
}
.largeTitle for main screen titles..title, .title2, .title3 for primary section titles..headline for emphasized labels..subheadline for secondary headings..body use for readable body text..callout for quote, important information, or a benefit statement..footnote for secondary text, such as disclaimers, or legal information.caption for small, secondary text such as descriptions accompanying images, disclaimers, or subtitles..caption2 for alternate, smaller captions.All system styles automatically support Dynamic Type it means these styles scale automatically when users change text size in Settings.
Font weight determines the thickness of characters, ranging from very light to very heavy. Use it to establish hierarchy without changing font size.
VStack(spacing: 12) {
Text("Ultra Light")
.fontWeight(.ultraLight)
Text("Thin")
.fontWeight(.thin)
Text("Light")
.fontWeight(.light)
Text("Regular")
.fontWeight(.regular)
Text("Medium")
.fontWeight(.medium)
Text("Semi Bold")
.fontWeight(.semibold)
Text("Bold")
.fontWeight(.bold)
Text("Heavy")
.fontWeight(.heavy)
Text("Black")
.fontWeight(.black)
}
.font(.title)
.regular for body text.medium or .semibold for labels.bold or .heavy sparingly for emphasisInstead of using only weight or size, combine font style + weight.
VStack(spacing: 12) {
Text("Invoices")
.font(.title) // title font style
.fontWeight(.heavy) // heavy weight
Text("Invoice Summary")
.font(.headline) // headline font style
.fontWeight(.semibold) // semibold weight
}
SwiftUI allows you to change the design of system fonts.
Available Designs
.default.rounded.monospaced.serifVStack(spacing: 12) {
Text("Default Design")
.font(.title)
Text("Rounded Design")
.font(.title)
.fontDesign(.rounded)
Text("Monospaced Design")
.font(.title)
.fontDesign(.monospaced)
Text("Serif Design")
.font(.title)
.fontDesign(.serif)
}
You can further adjust the system font’s style by using modifiers such as .italic() to italicize the text, .underline() to add an underline, and .strikethrough() to draw a line through the text.
VStack(spacing: 12) {
Text("Note: This feature is experimental")
.italic()
Text("Privacy Policy")
.underline()
Text("$49.99")
.strikethrough()
}
Starting with iOS 16, you can customize the .underline and .strikethrough by changing the line’s pattern and color. Pattern has these options: .dash, .dashDot, .dashDotDot, .dot,.solid.
VStack(spacing: 12) {
Text("Custom Underline")
.underline(pattern: .dash, color: .blue)
Text("Custom Strikethrough")
.strikethrough(pattern: .dot, color: .red)
Text("Mixed Styles")
.underline(pattern: .dashDot, color: .red)
.strikethrough(pattern: .solid)
}
.font(.title)
.italic() - Quoting text, scientific names, subtitles or captions, thoughts or narration in text content.underline() - Links, key terms or definitions, items requiring user attention.strikethrough() - Completed tasks in a to-do list, Discounted prices, Deprecated or unavailable itemsKerning adjusts the spacing between specific pairs of letters to improve visual balance and readability.
VStack(spacing: 12) {
Text("AV")
Text("AV")
.kerning(8)
}
.font(.title)
Tracking adjusts the spacing uniformly across all letters in a word or block of text.
VStack(spacing: 12) {
Text("WELCOME")
Text("WELCOME")
.tracking(8)
}
.font(.title)Line spacing is the distance from one line of text to the next.
VStack(spacing: 24) {
Text("""
SwiftUI automatically wraps text
onto multiple lines when needed.
Line spacing controls the vertical
distance between those lines.
""")
Text("""
SwiftUI automatically wraps text
onto multiple lines when needed.
Line spacing controls the vertical
distance between those lines.
""")
.lineSpacing(8)
}The value is measured in points and is added to the font’s default line height.
Baseline offset controls how text is shifted vertically relative to its baseline. The baseline is the invisible line on which most letters sit (like a, e, o), while letters such as g or y extend below it.
The .baselineOffset(_:) modifier lets you move text up or down without changing its font size or layout space.
VStack(spacing: 48) {
HStack(spacing: .zero) {
Text("10")
Text("2")
.font(.caption)
.baselineOffset(8)
}
HStack(spacing: .zero) {
Text("H")
Text("2")
.font(.caption)
.baselineOffset(-6)
Text("O")
}
}
Dynamic Type allows users to choose larger or smaller text sizes in iOS Accessibility settings. Supporting it properly ensures your app remains readable, usable, and inclusive for everyone.
System fonts is designed to work well with Dynamic Type by default—but there are important best practices to follow.
System text styles automatically scale with Dynamic Type.
VStack(spacing: 48) {
Text("Body text")
.font(.body)
Text("Headline")
.font(.headline)
Text("Title")
.font(.title)
}
Use system text styles whenever possible. Avoid fixed font sizes.
VStack(spacing: 24) {
Text("Fixed size")
.font(.system(size: 16))
Text("Fixed size")
.font(.system(size: 32))
Text("Fixed size")
.font(.system(size: 48))
}
VStack(spacing: 24) {
Text("Scalable title")
.font(.title)
Text("Scalable headline")
.font(.headline)
Text("Scalable body text")
.font(.body)
}
SwiftUI provides a typography system that is both powerful and opinionated. By using semantic system font styles, applying font modifiers intentionally, and respecting Dynamic Type and accessibility settings, you can create interfaces that remain readable, consistent, and adaptable across devices.
Custom fonts can be layered on top when branding requires it, but system fonts should remain the foundation for most user interfaces. Understanding how each font modifier affects text allows you to make precise typographic decisions while preserving accessibility and platform conventions. When used correctly, SwiftUI fonts help your UI communicate hierarchy, clarity, and intent without additional complexity.
If you have any suggestions, feel free to connect with me on X and send me a DM. If you enjoyed this article and would like to support me, Buy me a coffee.