UILabel
iOS
Swift
text resizing
auto-layout

Adjust UILabel height to text

Master System Design with Codemia

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

Introduction

Making a UILabel automatically resize its height to fit its text content is one of the most common iOS layout tasks. The key is setting numberOfLines = 0 (unlimited lines) and configuring Auto Layout constraints correctly. With proper setup, the label's intrinsic content size drives the layout, and the label grows or shrinks as text changes.

The simplest approach — let Auto Layout handle everything:

swift
1let label = UILabel()
2label.translatesAutoresizingMaskIntoConstraints = false
3label.numberOfLines = 0  // Allow unlimited lines
4label.lineBreakMode = .byWordWrapping
5label.text = "This is a long text that will wrap to multiple lines as needed."
6
7view.addSubview(label)
8
9NSLayoutConstraint.activate([
10    label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
11    label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
12    label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16)
13    // NO height constraint — label sizes itself
14])

With numberOfLines = 0 and leading/trailing constraints, the label calculates its own height based on the text, font, and available width.

Method 2: Interface Builder

In Storyboard/XIB:

  1. Select the UILabel
  2. Set Lines to 0 in the Attributes Inspector
  3. Add leading, trailing, and top (or vertical position) constraints
  4. Do not add a height constraint
  5. Set Content Hugging Priority (Vertical) to 251 (default) and Content Compression Resistance (Vertical) to 750

The label will resize to fit its content at runtime.

Method 3: sizeToFit() (Manual Frames)

If using manual frame layout instead of Auto Layout:

swift
1let label = UILabel(frame: CGRect(x: 16, y: 100, width: view.bounds.width - 32, height: 0))
2label.numberOfLines = 0
3label.text = "Long text that needs to wrap across multiple lines."
4label.sizeToFit()
5// label.frame.size.height is now set to fit the text

Method 4: sizeThatFits / boundingRect

Calculate the required height before setting the frame:

swift
1let label = UILabel()
2label.numberOfLines = 0
3label.font = UIFont.systemFont(ofSize: 16)
4label.text = "Calculate the required height for this text."
5
6// Method A: sizeThatFits
7let maxSize = CGSize(width: 300, height: CGFloat.greatestFiniteMagnitude)
8let requiredSize = label.sizeThatFits(maxSize)
9label.frame = CGRect(x: 16, y: 100, width: 300, height: requiredSize.height)
10
11// Method B: NSString.boundingRect
12let boundingRect = (label.text! as NSString).boundingRect(
13    with: maxSize,
14    options: [.usesLineFragmentOrigin, .usesFontLeading],
15    attributes: [.font: label.font!],
16    context: nil
17)
18let height = ceil(boundingRect.height)

Method 5: In UITableViewCell

For dynamic-height table view cells:

swift
1// In the cell class
2class TextCell: UITableViewCell {
3    let label = UILabel()
4
5    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
6        super.init(style: style, reuseIdentifier: reuseIdentifier)
7
8        label.numberOfLines = 0
9        label.translatesAutoresizingMaskIntoConstraints = false
10        contentView.addSubview(label)
11
12        NSLayoutConstraint.activate([
13            label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12),
14            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
15            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
16            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12)
17        ])
18    }
19
20    required init?(coder: NSCoder) { fatalError() }
21}
22
23// In the view controller
24tableView.rowHeight = UITableView.automaticDimension
25tableView.estimatedRowHeight = 60

The bottom constraint connecting the label to contentView.bottomAnchor is critical — it tells the cell to size itself based on the label's height.

Method 6: Attributed Text

For labels with mixed formatting:

swift
1let label = UILabel()
2label.numberOfLines = 0
3
4let text = NSMutableAttributedString()
5text.append(NSAttributedString(string: "Title\n",
6    attributes: [.font: UIFont.boldSystemFont(ofSize: 20)]))
7text.append(NSAttributedString(string: "Subtitle with a longer description",
8    attributes: [.font: UIFont.systemFont(ofSize: 14)]))
9
10label.attributedText = text
11// Height adjusts to both font sizes

preferredMaxLayoutWidth

When a label's width is ambiguous (e.g., in a cell before layout), set preferredMaxLayoutWidth to tell the label what width to use for line wrapping calculations:

swift
1override func layoutSubviews() {
2    super.layoutSubviews()
3    label.preferredMaxLayoutWidth = label.bounds.width
4    super.layoutSubviews()  // Second pass with correct width
5}

This is typically needed only when Auto Layout alone cannot determine the width.

Common Pitfalls

  • numberOfLines not set to 0: The default is 1, which truncates text. Always set numberOfLines = 0 for multiline labels.
  • Missing width constraint: Without a leading+trailing or width constraint, the label has no maximum width and will try to fit all text on one line, extending off-screen.
  • Height constraint conflicts: If you accidentally add a height constraint, it overrides the intrinsic content size. Remove it or set its priority below 750.
  • Content compression resistance: If other views are competing for space, ensure the label's vertical compression resistance priority (default 750) is high enough to prevent truncation.
  • sizeToFit() before setting text: sizeToFit() uses the current text. Call it after setting text and font, not before.

Summary

  • Set numberOfLines = 0 and provide leading/trailing constraints — no height constraint needed
  • Auto Layout uses the label's intrinsic content size to determine height automatically
  • For table view cells, pin the label to all four edges of contentView and use automaticDimension
  • Use sizeThatFits() or boundingRect when calculating height manually
  • preferredMaxLayoutWidth resolves ambiguous-width situations

Course illustration
Course illustration

All Rights Reserved.