UILabel
outlined text
iOS development
Swift
text customization

How do I make UILabel display outlined text?

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

UILabel does not expose a built-in "outline" switch, so outlined text requires either custom drawing or an attributed string with stroke attributes. The right choice depends on whether you need a reusable label class or a quick one-off style for a specific label.

Use a UILabel Subclass for a Reusable Solution

If you want outlined text in multiple places, subclassing UILabel is the cleanest approach. You keep Auto Layout behavior, alignment, line breaking, and normal label APIs while controlling how the text is drawn.

The usual pattern is to draw the stroke first and the fill second:

swift
1import UIKit
2
3final class OutlinedLabel: UILabel {
4    var outlineColor: UIColor = .black
5    var outlineWidth: CGFloat = 3
6
7    override func drawText(in rect: CGRect) {
8        guard let context = UIGraphicsGetCurrentContext() else {
9            super.drawText(in: rect)
10            return
11        }
12
13        let originalTextColor = textColor
14        let originalLineWidth = context.lineWidth
15        let originalMode = context.textDrawingMode
16
17        context.setLineWidth(outlineWidth)
18        context.setLineJoin(.round)
19
20        context.setTextDrawingMode(.stroke)
21        textColor = outlineColor
22        super.drawText(in: rect)
23
24        context.setTextDrawingMode(.fill)
25        textColor = originalTextColor
26        super.drawText(in: rect)
27
28        context.setLineWidth(originalLineWidth)
29        context.setTextDrawingMode(originalMode)
30    }
31}

This works because UIKit text drawing uses the current graphics context. By switching the drawing mode to .stroke, you get the border; by switching back to .fill, you get the normal interior.

Configure the Custom Label

You can use the subclass programmatically like any other label:

swift
1let label = OutlinedLabel()
2label.text = "Outlined title"
3label.textColor = .white
4label.outlineColor = .black
5label.outlineWidth = 4
6label.font = UIFont.boldSystemFont(ofSize: 30)
7label.textAlignment = .center
8label.numberOfLines = 0

If you prefer Storyboards or XIBs, set the label's custom class to OutlinedLabel. If design-time control matters, expose the stroke settings to Interface Builder:

swift
1import UIKit
2
3final class InspectableOutlinedLabel: UILabel {
4    @IBInspectable var outlineWidth: CGFloat = 2
5    @IBInspectable var outlineUIColor: UIColor = .black
6
7    override func drawText(in rect: CGRect) {
8        guard let context = UIGraphicsGetCurrentContext() else {
9            super.drawText(in: rect)
10            return
11        }
12
13        let fillColor = textColor
14        context.setLineWidth(outlineWidth)
15        context.setLineJoin(.round)
16
17        context.setTextDrawingMode(.stroke)
18        textColor = outlineUIColor
19        super.drawText(in: rect)
20
21        context.setTextDrawingMode(.fill)
22        textColor = fillColor
23        super.drawText(in: rect)
24    }
25}

That makes it easier to experiment without recompiling for every small visual change.

Attributed Strings Are Fine for One-Off Labels

If you do not need a custom subclass, NSAttributedString can apply a fill and a stroke directly:

swift
1import UIKit
2
3let attributes: [NSAttributedString.Key: Any] = [
4    .foregroundColor: UIColor.white,
5    .strokeColor: UIColor.black,
6    .strokeWidth: -3.0
7]
8
9let outlined = NSAttributedString(string: "Outlined title", attributes: attributes)
10
11let label = UILabel()
12label.attributedText = outlined

The negative stroke width is important. In UIKit drawing, a negative value means "draw fill and stroke." A positive value usually produces only the stroke.

This approach is simple, but it is less reusable when every outlined label in the app should behave consistently.

Layout and Rendering Considerations

Outlined text visually occupies a little more space than plain text, even when the label frame stays the same. Test a few things before shipping:

  • Large font sizes.
  • Multi-line labels.
  • Dynamic Type sizes.
  • Light and dark backgrounds.

If the outline touches the label edge, increase padding around the label or place it inside a container view. Thick strokes can make descenders and punctuation look cramped.

Performance is usually fine for a few labels, but custom drawing is still extra work. Avoid putting heavily outlined labels inside fast-scrolling lists unless you have actually tested it.

When a Different Effect Is Better

Sometimes people ask for outlined text when they really want a shadow or a layered title effect. A shadow is cheaper and often more readable:

swift
label.textColor = .white
label.shadowColor = .black
label.shadowOffset = CGSize(width: 1, height: 1)

That is not a true outline, but for many headers it solves the readability problem with less custom code.

Common Pitfalls

  • Expecting a stock UILabel property to enable a true text outline.
  • Drawing the stroke but forgetting to redraw the fill.
  • Using a positive strokeWidth with attributed text and wondering why the fill disappeared.
  • Choosing a very thick outline that reduces readability instead of improving it.
  • Forgetting to test long strings, large fonts, and multi-line layout.

Summary

  • 'UILabel does not provide a built-in outlined text option.'
  • A custom subclass is the best reusable approach when the style appears in multiple places.
  • 'NSAttributedString with stroke attributes is a good one-off solution.'
  • Negative strokeWidth values are typically required for fill plus stroke rendering.
  • Test outlined text with real font sizes and layouts so the effect stays readable.

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.