Skip to Content
Course content

204: Dynamic Type Support

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've seen plenty of developers spend weeks polishing a UI, only to realize they've completely ignored accessibility. One of the most common oversights is Dynamic Type. If a user has bumped up their system font size because they actually need to see the text to use your app, and your layout stays frozen at 16pt, you've essentially locked them out.

Why your fixed font sizes are hurting users

The instinct is often to pick a "perfect" font size—say, 17pt for body text—and call it a day. But in iOS, we shouldn't be picking sizes; we should be picking roles. Apple provides "Text Styles" (like .headline, .body, and .caption1) that automatically scale based on the user's system settings.

Let's build a simple ArticlePreviewView. We want a bold headline and a short summary. If we do this the "old way," we're just setting a constant font. But to support Dynamic Type, we use the preferred font for a specific style.

class ArticlePreviewView: UIView {
    let headlineLabel = UILabel()
    let summaryLabel = UILabel()

    func setupView() {
        // Instead of UIFont.systemFont(ofSize: 20), we use:
        headlineLabel.font = UIFont.preferredFont(forTextStyle: .headline)
        summaryLabel.font = UIFont.preferredFont(forTextStyle: .body)
        
        headlineLabel.text = "The Future of Swift"
        summaryLabel.text = "Exploring the latest concurrency features and how they change the way we write async code."
        summaryLabel.numberOfLines = 0 // Essential so text can wrap as it grows
    }
}

The missing link: Real-time updates

Now, here is where I almost tripped up the first time I implemented this. I ran the app, went into the iOS Settings app, changed the text size to "Extra Large," and switched back to my app. Nothing happened. The text was still small. I thought the code was broken.

What I forgot is that UIFont.preferredFont only sets the font size at the moment the label is created. It doesn't automatically listen for system changes while the app is running. To make the label update its size dynamically without requiring a restart, you have to explicitly tell the label to adjust itself.

// This is the line I missed. Without this, Dynamic Type is only "half" working.
headlineLabel.adjustsFontForContentSizeCategory = true
summaryLabel.adjustsFontForContentSizeCategory = true

Adding those two lines tells UIKit to observe the UIContentSizeCategory.didChangeNotification and update the font immediately. It's a tiny bit of code, but it's the difference between a professional app and one that feels broken to an accessibility user.

Letting the layout breathe

Once the text actually scales, you'll notice a new problem: your layout will likely break. If you used hard-coded heights (like heightAnchor.constraint(equalToConstant: 100)), your text will either clip or overlap as it grows.

The solution is to lean heavily on UIStackView. Stacks are naturally flexible. By putting our labels in a vertical stack with alignment = .fill and distribution = .fill, the container will simply grow taller as the font size increases. I always recommend avoiding fixed heights whenever text is involved; let the content dictate the size of the container.

let stackView = UIStackView(arrangedSubviews: [headlineLabel, summaryLabel])
stackView.axis = .vertical
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false

addSubview(stackView)
// Constrain to edges, but NEVER set a fixed height for the stackView itself.
NSLayoutConstraint.activate([
    stackView.topAnchor.constraint(equalTo: topAnchor, constant: 16),
    stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
    stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
    stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -16)
])



📋 Practical Task

Refactoring the User Profile Card for Dynamic Type

You have been handed a UserProfileView that uses fixed font sizes and a fixed-height container, which makes the text clip when a user increases their system font size. Your task is to refactor this view to be fully accessible.

Requirements:

  • Replace UIFont.systemFont(ofSize: 22) for the username with the .title2 preferred text style.
  • Replace UIFont.systemFont(ofSize: 14) for the bio with the .subheadline preferred text style.
  • Enable real-time font updating for both labels so the user doesn't have to restart the app.
  • Remove the fixed height constraint on the main container view and replace it with a UIStackView or flexible constraints that allow the view to expand vertically as the text grows.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.