UILabel
iOS Development
Swift
Dynamic Font Size
Mobile App Design

Dynamically changing font size of UILabel

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

UILabel can automatically shrink its font to fit text within its bounds using adjustsFontSizeToFitWidth and minimumScaleFactor. For programmatic control, set the font property directly. For system-wide Dynamic Type support (accessibility), use UIFont.preferredFont(forTextStyle:) with adjustsFontForContentSizeCategory = true. Each approach serves a different use case — auto-shrinking for layout constraints, programmatic changes for state-driven UI, and Dynamic Type for accessibility.

Auto-Shrinking to Fit Width

swift
1let label = UILabel()
2label.text = "This is a very long text that might not fit"
3label.font = UIFont.systemFont(ofSize: 24)
4
5// Enable auto-shrinking
6label.adjustsFontSizeToFitWidth = true
7label.minimumScaleFactor = 0.5  // Shrink down to 50% of original size (12pt)
8
9// Required for shrinking to work
10label.numberOfLines = 1  // Single line only

minimumScaleFactor is a ratio of the original font size. A value of 0.5 with a 24pt font allows shrinking down to 12pt. The label shrinks only when the text does not fit at the original size.

Setting Font Size Programmatically

swift
1let label = UILabel()
2
3// Set initial font
4label.font = UIFont.systemFont(ofSize: 16)
5
6// Change font size based on a condition
7func updateFontSize(isLarge: Bool) {
8    let size: CGFloat = isLarge ? 24 : 16
9    label.font = UIFont.systemFont(ofSize: size)
10}
11
12// Animate the change
13UIView.transition(with: label, duration: 0.3, options: .transitionCrossDissolve) {
14    label.font = UIFont.systemFont(ofSize: 32)
15}

Dynamic Type (Accessibility)

swift
1let label = UILabel()
2
3// Use a text style that responds to system font size settings
4label.font = UIFont.preferredFont(forTextStyle: .body)
5
6// Automatically update when the user changes system font size
7label.adjustsFontForContentSizeCategory = true
8
9// Available text styles:
10// .largeTitle, .title1, .title2, .title3
11// .headline, .subheadline
12// .body, .callout, .footnote, .caption1, .caption2

When the user changes the system font size in Settings > Accessibility > Display & Text Size, labels with adjustsFontForContentSizeCategory = true update automatically.

Custom Fonts with Dynamic Type

swift
1// Scale a custom font with Dynamic Type
2let customFont = UIFont(name: "Avenir-Medium", size: 16)!
3label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: customFont)
4label.adjustsFontForContentSizeCategory = true

UIFontMetrics scales your custom font proportionally to the user's Dynamic Type setting.

Auto Layout Considerations

swift
1// For multi-line labels that should grow/shrink with content
2let label = UILabel()
3label.font = UIFont.preferredFont(forTextStyle: .body)
4label.numberOfLines = 0  // Unlimited lines
5label.lineBreakMode = .byWordWrapping
6
7// Set content hugging and compression resistance
8label.setContentHuggingPriority(.required, for: .vertical)
9label.setContentCompressionResistancePriority(.required, for: .vertical)
10
11// Preferred max layout width for proper wrapping in stack views
12label.preferredMaxLayoutWidth = 300

Scaling Based on Screen Size

swift
1func scaledFontSize(base: CGFloat) -> CGFloat {
2    let screenWidth = UIScreen.main.bounds.width
3    let referenceWidth: CGFloat = 375  // iPhone SE/8 width
4    return base * (screenWidth / referenceWidth)
5}
6
7label.font = UIFont.systemFont(ofSize: scaledFontSize(base: 16))
8// iPhone SE: 16pt, iPhone 14 Pro Max: ~18.6pt

Attributed Text with Multiple Sizes

swift
1let text = NSMutableAttributedString()
2
3let title = NSAttributedString(
4    string: "Title\n",
5    attributes: [.font: UIFont.boldSystemFont(ofSize: 24)]
6)
7let body = NSAttributedString(
8    string: "Body text goes here",
9    attributes: [.font: UIFont.systemFont(ofSize: 14)]
10)
11
12text.append(title)
13text.append(body)
14
15label.numberOfLines = 0
16label.attributedText = text

Interface Builder Configuration

In Storyboard or XIB:

  1. Select the UILabel
  2. In the Attributes inspector:
    • Font: Choose the font and size
    • Autoshrink: Set to "Minimum Font Scale" and enter a value (e.g., 0.5)
    • Lines: Set to 1 for auto-shrinking, 0 for multi-line wrapping
  3. For Dynamic Type: set Font to a text style (Body, Title, etc.) and check "Automatically Adjusts Font"

Responding to Content Size Changes

swift
1class ViewController: UIViewController {
2    let label = UILabel()
3
4    override func viewDidLoad() {
5        super.viewDidLoad()
6
7        label.font = UIFont.preferredFont(forTextStyle: .body)
8        label.adjustsFontForContentSizeCategory = true
9
10        // Or manually observe changes
11        NotificationCenter.default.addObserver(
12            self,
13            selector: #selector(contentSizeCategoryChanged),
14            name: UIContentSizeCategory.didChangeNotification,
15            object: nil
16        )
17    }
18
19    @objc func contentSizeCategoryChanged() {
20        // Recalculate custom layouts based on new font sizes
21        label.font = UIFont.preferredFont(forTextStyle: .body)
22        view.setNeedsLayout()
23    }
24}

Common Pitfalls

  • adjustsFontSizeToFitWidth requires numberOfLines = 1: Auto-shrinking only works for single-line labels. For multi-line labels, use numberOfLines = 0 with auto layout constraints and let the label grow vertically instead.
  • minimumScaleFactor = 0: A scale factor of 0 means the text can shrink to nearly invisible. Set a reasonable minimum like 0.5 or 0.7 to keep text readable.
  • Ignoring Dynamic Type: Apps that do not support Dynamic Type fail accessibility reviews. Always use preferredFont(forTextStyle:) for user-facing text.
  • Overriding font in layoutSubviews: Setting label.font in layoutSubviews causes an infinite loop because changing the font triggers a layout pass. Set fonts in viewDidLoad or when data changes, not in layout methods.
  • Mixing text and attributedText: Setting attributedText overrides text and vice versa. If you set an attributed string, subsequent label.font = ... changes are ignored — modify the attributed string's attributes instead.

Summary

  • Use adjustsFontSizeToFitWidth = true with minimumScaleFactor for auto-shrinking single-line labels
  • Set label.font = UIFont.systemFont(ofSize:) for programmatic size changes
  • Use UIFont.preferredFont(forTextStyle:) with adjustsFontForContentSizeCategory = true for Dynamic Type accessibility
  • Scale custom fonts with UIFontMetrics(forTextStyle:).scaledFont(for:)
  • For multi-line labels, use numberOfLines = 0 with auto layout instead of auto-shrinking

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.