UILabel
iOS development
padding
user interface
Swift programming

Adding space/padding to a UILabel

Master System Design with Codemia

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

Introduction

UILabel does not provide a direct padding property, so internal spacing must be implemented with a custom approach. The most reliable method is subclassing and drawing text inside inset bounds. With a small reusable subclass, you can keep interface code clean and support both Auto Layout and Interface Builder.

Subclass UILabel with Text Insets

Override text drawing and intrinsic size so padding affects both rendering and layout.

swift
1import UIKit
2
3final class PaddedLabel: UILabel {
4    var textInsets = UIEdgeInsets(top: 6, left: 10, bottom: 6, right: 10) {
5        didSet {
6            invalidateIntrinsicContentSize()
7            setNeedsDisplay()
8        }
9    }
10
11    override func drawText(in rect: CGRect) {
12        super.drawText(in: rect.inset(by: textInsets))
13    }
14
15    override var intrinsicContentSize: CGSize {
16        let size = super.intrinsicContentSize
17        return CGSize(
18            width: size.width + textInsets.left + textInsets.right,
19            height: size.height + textInsets.top + textInsets.bottom
20        )
21    }
22
23    override func sizeThatFits(_ size: CGSize) -> CGSize {
24        let base = super.sizeThatFits(
25            CGSize(
26                width: size.width - textInsets.left - textInsets.right,
27                height: size.height - textInsets.top - textInsets.bottom
28            )
29        )
30
31        return CGSize(
32            width: base.width + textInsets.left + textInsets.right,
33            height: base.height + textInsets.top + textInsets.bottom
34        )
35    }
36}

This makes spacing behavior explicit and reusable across screens.

Use the Padded Label in Layouts

After creating the subclass, treat it like a normal label in constraints.

swift
1import UIKit
2
3final class BadgeViewController: UIViewController {
4    private let badge = PaddedLabel()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        view.backgroundColor = .systemBackground
9
10        badge.translatesAutoresizingMaskIntoConstraints = false
11        badge.textInsets = UIEdgeInsets(top: 4, left: 12, bottom: 4, right: 12)
12        badge.text = "New"
13        badge.backgroundColor = .systemBlue
14        badge.textColor = .white
15        badge.layer.cornerRadius = 12
16        badge.layer.masksToBounds = true
17
18        view.addSubview(badge)
19
20        NSLayoutConstraint.activate([
21            badge.centerXAnchor.constraint(equalTo: view.centerXAnchor),
22            badge.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20)
23        ])
24    }
25}

Because intrinsic content size is updated, Auto Layout can size the badge correctly.

Alternative Approaches

You can simulate spacing by wrapping a label inside a container view and constraining it with inner margins. That works, but adds more view hierarchy and can complicate reusable cells.

Attributed strings also support paragraph and line spacing, but not simple uniform inner edge padding. For consistent box-style padding, subclassing or container views remain the strongest options.

Interface Builder Support

If designers use storyboard or xib files, expose inset values as inspectable properties.

swift
1import UIKit
2
3extension PaddedLabel {
4    @IBInspectable var topInset: CGFloat {
5        get { textInsets.top }
6        set { textInsets.top = newValue }
7    }
8
9    @IBInspectable var leftInset: CGFloat {
10        get { textInsets.left }
11        set { textInsets.left = newValue }
12    }
13
14    @IBInspectable var bottomInset: CGFloat {
15        get { textInsets.bottom }
16        set { textInsets.bottom = newValue }
17    }
18
19    @IBInspectable var rightInset: CGFloat {
20        get { textInsets.right }
21        set { textInsets.right = newValue }
22    }
23}

This allows quick visual tuning without editing code for every spacing change.

Multiline Text and Dynamic Type

Padding should work with multiline content and user-selected text sizes. Set numberOfLines = 0 and use preferred text styles so labels respond to Dynamic Type. Then test with large accessibility sizes to confirm that padded text still fits within container constraints. If using badges or chips, consider whether text should truncate or wrap at larger sizes. A reusable padded label class with clear size behavior makes these accessibility adjustments straightforward across the app.

Common Pitfalls

A frequent mistake is overriding drawText but not intrinsicContentSize. Text appears padded visually, but layout still uses old size, causing clipping.

Another issue is changing insets without invalidating intrinsic size. Auto Layout may not recalculate dimensions until a later layout pass.

Developers also use fixed width and height constraints that conflict with dynamic text plus padding. Prefer flexible constraints unless the design requires strict dimensions.

Finally, in reusable views, always set insets during configuration to avoid stale values from earlier content.

Summary

  • UILabel has no built-in padding property.
  • Subclassing with inset-aware drawing and intrinsic size is the cleanest approach.
  • Use Auto Layout with flexible constraints for dynamic text.
  • Add inspectable inset properties for storyboard workflows.
  • Recalculate layout when inset values change.

Course illustration
Course illustration

All Rights Reserved.