SwiftUI
iOS Development
Custom Font
Text Styling
Swift Programming

Custom font size for Text in SwiftUI

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In SwiftUI, customize font size for Text views using .font(.system(size:)) for system fonts, .font(.custom("FontName", size:)) for custom fonts, or .font(.title) for semantic text styles that scale with Dynamic Type. SwiftUI's built-in text styles (.body, .title, .caption, etc.) automatically support accessibility scaling, while fixed-size fonts require explicit opt-in via @ScaledMetric or .dynamicTypeSize().

System Fonts with Custom Size

swift
1import SwiftUI
2
3struct FontExamples: View {
4    var body: some View {
5        VStack(alignment: .leading, spacing: 12) {
6            Text("Size 12")
7                .font(.system(size: 12))
8
9            Text("Size 20, Bold")
10                .font(.system(size: 20, weight: .bold))
11
12            Text("Size 28, Light, Rounded")
13                .font(.system(size: 28, weight: .light, design: .rounded))
14
15            Text("Size 16, Monospaced")
16                .font(.system(size: 16, weight: .regular, design: .monospaced))
17
18            Text("Size 24, Serif")
19                .font(.system(size: 24, weight: .medium, design: .serif))
20        }
21    }
22}

Available weights: .ultraLight, .thin, .light, .regular, .medium, .semibold, .bold, .heavy, .black.

Available designs: .default, .rounded, .monospaced, .serif.

SwiftUI provides text styles that scale automatically with the user's Dynamic Type setting:

swift
1VStack(alignment: .leading, spacing: 8) {
2    Text("Large Title").font(.largeTitle)    // ~34pt
3    Text("Title").font(.title)               // ~28pt
4    Text("Title 2").font(.title2)            // ~22pt
5    Text("Title 3").font(.title3)            // ~20pt
6    Text("Headline").font(.headline)         // ~17pt bold
7    Text("Body").font(.body)                 // ~17pt
8    Text("Callout").font(.callout)           // ~16pt
9    Text("Subheadline").font(.subheadline)   // ~15pt
10    Text("Footnote").font(.footnote)         // ~13pt
11    Text("Caption").font(.caption)           // ~12pt
12    Text("Caption 2").font(.caption2)        // ~11pt
13}

These styles are the best choice for most UI text because they respect the user's accessibility preferences.

Custom Fonts

Load a custom font file (.ttf or .otf) included in your app bundle:

swift
1// Step 1: Add font file to your project
2// Step 2: Add to Info.plist under "Fonts provided by application"
3
4Text("Custom Font")
5    .font(.custom("Avenir-Heavy", size: 24))
6
7Text("Fixed Size Custom Font")
8    .font(.custom("Georgia", fixedSize: 18))
9
10// With relative sizing (scales with Dynamic Type)
11Text("Relative Custom Font")
12    .font(.custom("Avenir", size: 17, relativeTo: .body))

Registering Custom Fonts in Info.plist

xml
1<key>UIAppFonts</key>
2<array>
3    <string>MyCustomFont-Regular.ttf</string>
4    <string>MyCustomFont-Bold.ttf</string>
5</array>

Dynamic Type Scaling

@ScaledMetric for Custom Sizes

swift
1struct ScaledFontView: View {
2    @ScaledMetric(relativeTo: .body) var fontSize: CGFloat = 17
3
4    var body: some View {
5        Text("This scales with Dynamic Type")
6            .font(.system(size: fontSize))
7    }
8}

@ScaledMetric adjusts the value proportionally when the user changes their preferred text size in Settings.

Limiting Dynamic Type Range

swift
1Text("Bounded scaling")
2    .font(.title)
3    .dynamicTypeSize(.small ... .xxxLarge)  // Limits scaling range
4
5Text("Fixed size, no scaling")
6    .font(.system(size: 20))
7    .dynamicTypeSize(.large)  // Locks to one size

Text Modifiers

Combine font size with other text styling:

swift
1Text("Styled Text")
2    .font(.system(size: 22, weight: .bold, design: .rounded))
3    .foregroundColor(.blue)
4    .italic()
5    .underline()
6    .tracking(2)        // Letter spacing
7    .lineSpacing(8)     // Line height
8    .multilineTextAlignment(.center)
9
10// Combining multiple styles in one Text
11Text("Hello ")
12    .font(.title) +
13Text("World")
14    .font(.caption)
15    .foregroundColor(.gray)

Font Weight Without Changing Size

swift
1Text("Bold body text")
2    .font(.body)
3    .fontWeight(.bold)
4
5Text("Light headline")
6    .font(.headline)
7    .fontWeight(.light)
8
9// Bold shorthand
10Text("Bold shorthand")
11    .bold()

Conditional Font Sizes

swift
1struct AdaptiveText: View {
2    @Environment(\.horizontalSizeClass) var sizeClass
3
4    var body: some View {
5        Text("Adaptive")
6            .font(.system(size: sizeClass == .compact ? 16 : 24))
7    }
8}
9
10// Based on platform
11struct PlatformText: View {
12    var body: some View {
13        Text("Cross-platform")
14            #if os(iOS)
15            .font(.system(size: 17))
16            #elseif os(macOS)
17            .font(.system(size: 13))
18            #endif
19    }
20}

Custom Font Extension

Create a reusable font system:

swift
1extension Font {
2    static func appFont(size: CGFloat, weight: Font.Weight = .regular) -> Font {
3        .custom("Avenir", size: size).weight(weight)
4    }
5
6    static let appTitle = Font.custom("Avenir-Heavy", size: 28, relativeTo: .title)
7    static let appBody = Font.custom("Avenir", size: 17, relativeTo: .body)
8    static let appCaption = Font.custom("Avenir-Light", size: 12, relativeTo: .caption)
9}
10
11// Usage
12Text("Title").font(.appTitle)
13Text("Body text").font(.appBody)
14Text("Caption").font(.appCaption)

Common Pitfalls

  • Using fixed font sizes instead of semantic text styles: .font(.system(size: 17)) does not scale with Dynamic Type. Users with accessibility needs see the same small text regardless of their settings. Use .font(.body) or .custom("Font", size: 17, relativeTo: .body) for accessible text.
  • Wrong custom font name string: The font name passed to .custom() must be the PostScript name, not the file name. Use UIFont.familyNames and UIFont.fontNames(forFamilyName:) to find the correct name. A wrong name silently falls back to the system font.
  • Forgetting to register fonts in Info.plist: Custom font files must be listed under UIAppFonts in Info.plist and included in the app target. Without registration, .custom("MyFont", size: 20) silently uses the system font instead.
  • Setting .fontWeight() on a custom font: .fontWeight() only works with system fonts. For custom fonts, use the specific font variant name (e.g., "Avenir-Heavy" instead of "Avenir" with .bold()).
  • Not testing with large Dynamic Type sizes: Text that looks fine at default size may clip, overlap, or break layouts at the largest accessibility sizes. Always test with Xcode > Accessibility Inspector or .environment(\.sizeCategory, .accessibilityExtraExtraExtraLarge).

Summary

  • Use .font(.system(size:weight:design:)) for system fonts with specific sizes
  • Use .font(.body), .font(.title), etc. for accessible, auto-scaling text
  • Use .font(.custom("FontName", size:, relativeTo:)) for custom fonts that scale with Dynamic Type
  • Use @ScaledMetric to make custom numeric values scale with accessibility settings
  • Create a Font extension for consistent typography across your app

Course illustration
Course illustration

All Rights Reserved.