I'm looking to set the left inset/margin of a UILabel
and can't find a method to do so. The label has a background set so just changing its origin won't do the trick. It would be ideal to inset the text by 10px
or so on the left hand side.

- 3,221
- 5
- 30
- 41

- 12,091
- 11
- 45
- 60
-
once you subclass, for the insets it is simply, https://stackoverflow.com/a/43197662/294884 – Fattie Jun 05 '18 at 02:20
-
Another approach may be embedding your label in a horizontal stackview and add uiview left / right of any width you wish. – ugur Jun 06 '18 at 14:11
-
We have finally, finally completely solved this problem. You must call super LAST in textRect: https://stackoverflow.com/a/58876988/294884 – Fattie Nov 15 '19 at 12:23
38 Answers
I solved this by subclassing UILabel
and overriding drawTextInRect:
like this:
- (void)drawTextInRect:(CGRect)rect {
UIEdgeInsets insets = {0, 5, 0, 5};
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
Swift 3.1:
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets.init(top: 0, left: 5, bottom: 0, right: 5)
super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
}
Swift 4.2.1:
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
super.drawText(in: rect.inset(by: insets))
}
As you might have gathered, this is an adaptation of tc.'s answer. It has two advantages over that one:
- there's no need to trigger it by sending a
sizeToFit
message - it leaves the label frame alone - handy if your label has a background and you don't want that to shrink

- 4,168
- 4
- 30
- 57

- 20,407
- 14
- 52
- 57
-
2
-
15You might want to check out [this answer](http://stackoverflow.com/a/21267507/104790) which properly deals with sizeToFit and auto layout. – Nikolai Ruhe Jan 21 '14 at 19:48
-
I'm finding that this approach doesn't play nice with sizeWithFont:constrainedToSize:... frame resizing; is that anyone else's experience? – weienw Jan 23 '14 at 19:04
-
2You will also need to subclass `editingRectForBounds:` if you want to have the inset while entering text. – fabb May 09 '14 at 09:51
-
It could be useful to add the insets as a property to the new class, so the user could adjust them as needed. e.g. @property (nonatomic) UIEdgeInsets edgeInsets; – Don Miguel Jun 23 '14 at 13:56
-
I had to override `-sizeThatFits:(CGSize)size` as well, since my subclass does some calculations for font size etc. Thanks, that's a brilliant solution! – Nir Golan Jul 17 '14 at 21:57
-
21You should also override `intrinsicContentSize` so that it works with auto layout. I've added that to the sample code in [@Brody's](http://stackoverflow.com/a/17557490/1693173) answer. – progrmr Jul 28 '14 at 13:02
-
13I don't understand how this answer could get so many upvotes?! This approach will most probably cause many issue regarding lineBreakingMode and placement of ellipsis. The computed needed size for the string isn't equal the size given to drawing it, or am I wrong? – Patrik Mar 02 '15 at 15:09
-
`drawTextInRect` is public so must be `override public func drawTextInRect` – Stepan Maksymov Sep 01 '16 at 12:06
-
I am getting runtime exception "can not cast..." . I want to do the same thing with a UILabel obtained from viewWithTag method of UITableViewCell. Anyone can help ? – Abdul Hannan Sep 14 '16 at 15:41
-
Its not working for me, here is my code: https://stackoverflow.com/q/45218242/2652541 – kurrodu Jul 20 '17 at 23:17
-
overriding drawTextInRect cannot work correctly for NSAttributedString – Harrison Xi Mar 28 '18 at 15:09
-
I think the most simple way is adding some spaces to that particular string:[UILabel setText:[NSString stringWithFormat:@" %@ ", text]]; XD – steven Nov 08 '18 at 10:50
-
This is good without constraints. When I apply auto layout constraints, this won't work..... because in the given width and height, it will apply the padding and text will be truncated. – Satyam Aug 31 '19 at 07:31
-
This is quite wrong. The full answer: https://stackoverflow.com/a/58876988/294884 – Fattie Nov 15 '19 at 12:24
-
Failed to set (topInset) user defined inspected property on (SLMobile.TextTopLeftLabel): [
setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key topInset. Doesn't work. – John Pitts Aug 12 '21 at 16:33
For multiline text the left and the right margin can be set by using NSAttributedString.
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
style.alignment = NSTextAlignmentJustified;
style.firstLineHeadIndent = 10.0f;
style.headIndent = 10.0f;
style.tailIndent = -10.0f;
NSAttributedString *attrText = [[NSAttributedString alloc] initWithString:title attributes:@{ NSParagraphStyleAttributeName : style}];
UILabel * label = [[UILabel alloc] initWithFrame:someFrame];
label.numberOfLines = 0;
label.attributedText = attrText;
Here is the above example adopted to Swift 5:
extension UILabel {
func setMargins(margin: CGFloat = 10) {
if let textString = self.text {
var paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.firstLineHeadIndent = margin
paragraphStyle.headIndent = margin
paragraphStyle.tailIndent = -margin
let attributedString = NSMutableAttributedString(string: textString)
attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
attributedText = attributedString
}
}
}
-
4
-
4Can't add tailIndent = -10 in IB, allows only positive values :/ – HamzaGhazouani May 15 '15 at 12:25
-
2
-
-
Thanks but that extension doesn't work if you're already using attributedText on the label. However it contains the lines of the code needed to modify the attributed text in place. – clearlight Sep 11 '22 at 01:54
The best approach to add padding to a UILabel is to subclass UILabel and add an edgeInsets property. You then set the desired insets and the label will be drawn accordingly.
OSLabel.h
#import <UIKit/UIKit.h>
@interface OSLabel : UILabel
@property (nonatomic, assign) UIEdgeInsets edgeInsets;
@end
OSLabel.m
#import "OSLabel.h"
@implementation OSLabel
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
}
return self;
}
- (void)drawTextInRect:(CGRect)rect {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.edgeInsets)];
}
- (CGSize)intrinsicContentSize
{
CGSize size = [super intrinsicContentSize];
size.width += self.edgeInsets.left + self.edgeInsets.right;
size.height += self.edgeInsets.top + self.edgeInsets.bottom;
return size;
}
@end

- 75,956
- 16
- 112
- 147

- 8,506
- 2
- 47
- 42
-
6
-
5There's a problem with this solution - the last line of the label text will be cut off if the text is sufficiently long enough and if the insets are large enough. Just tried with the latest iOS 7. – BVB Jul 23 '14 at 18:06
-
5You should also override `intrinsicContentSize` to increase the intrinsic size to include the insets so that auto layout will work properly. – progrmr Jul 28 '14 at 01:39
-
1
-
3
-
2@AsifBilal you need to also override the `textRectForBounds:` method. – Kostub Deshmukh Oct 28 '16 at 07:02
-
This is not quite the full answer. Note the image example showing the problem here: https://stackoverflow.com/a/58876988/294884 – Fattie Nov 15 '19 at 12:25
Subclassing is a little cumbersome for such a simple case. An alternative is to simply add the UILabel with no background set to a UIView with the background set. Set the label's x to 10 and make the outer view's size 20 pixels wider than the label.

- 18,141
- 8
- 79
- 101
-
8*cough* the outer view would need to be _20_ points wider than the label. 10 on each side. – Tommy Feb 26 '16 at 17:25
-
2While subclassing would create a reusable component, this approach did save me time. Thank you, Peter – SagarU Apr 20 '18 at 20:59
-
Keep in mind that the UILabel already is already subclassing a UIView so doing this would be a bit redundant, but it does achieve the goal. – Cyril Jun 23 '20 at 18:51
-
Oftentimes in XCode, we look for the complex answers. This the simplest and most effective and layering views can solve many more problems. In fact, back in the day, NS (NextStep) designed views for this very purpose. With the advent of constraints, many of us have forgotten just how simple (and fast) things can be by just using views. – PDG Sep 09 '20 at 18:09
With Swift 3, you can have the desired effect by creating a subclass of UILabel
. In this subclass, you will have to add a UIEdgeInsets
property with the required insets and override drawText(in:)
method, intrinsicContentSize
property (for Auto layout code) and/or sizeThatFits(_:)
method (for Springs & Struts code).
import UIKit
class PaddingLabel: UILabel {
let padding: UIEdgeInsets
// Create a new PaddingLabel instance programamtically with the desired insets
required init(padding: UIEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)) {
self.padding = padding
super.init(frame: CGRect.zero)
}
// Create a new PaddingLabel instance programamtically with default insets
override init(frame: CGRect) {
padding = UIEdgeInsets.zero // set desired insets value according to your needs
super.init(frame: frame)
}
// Create a new PaddingLabel instance from Storyboard with default insets
required init?(coder aDecoder: NSCoder) {
padding = UIEdgeInsets.zero // set desired insets value according to your needs
super.init(coder: aDecoder)
}
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, padding))
}
// Override `intrinsicContentSize` property for Auto layout code
override var intrinsicContentSize: CGSize {
let superContentSize = super.intrinsicContentSize
let width = superContentSize.width + padding.left + padding.right
let height = superContentSize.height + padding.top + padding.bottom
return CGSize(width: width, height: height)
}
// Override `sizeThatFits(_:)` method for Springs & Struts code
override func sizeThatFits(_ size: CGSize) -> CGSize {
let superSizeThatFits = super.sizeThatFits(size)
let width = superSizeThatFits.width + padding.left + padding.right
let heigth = superSizeThatFits.height + padding.top + padding.bottom
return CGSize(width: width, height: heigth)
}
}
The following example shows how to use PaddingLabel
instances in a UIViewController
:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var storyboardAutoLayoutLabel: PaddingLabel!
let autoLayoutLabel = PaddingLabel(padding: UIEdgeInsets(top: 20, left: 40, bottom: 20, right: 40))
let springsAndStructsLabel = PaddingLabel(frame: CGRect.zero)
var textToDisplay = "Lorem ipsum dolor sit er elit lamet."
override func viewDidLoad() {
super.viewDidLoad()
// Set autoLayoutLabel
autoLayoutLabel.text = textToDisplay
autoLayoutLabel.backgroundColor = .red
autoLayoutLabel.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(autoLayoutLabel)
autoLayoutLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
autoLayoutLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
// Set springsAndStructsLabel
springsAndStructsLabel.text = textToDisplay
springsAndStructsLabel.backgroundColor = .green
view.addSubview(springsAndStructsLabel)
springsAndStructsLabel.frame.origin = CGPoint(x: 30, y: 90)
springsAndStructsLabel.sizeToFit()
// Set storyboardAutoLayoutLabel
storyboardAutoLayoutLabel.text = textToDisplay
storyboardAutoLayoutLabel.backgroundColor = .blue
}
// Link this IBAction to a UIButton or a UIBarButtonItem in Storyboard
@IBAction func updateLabelText(_ sender: Any) {
textToDisplay = textToDisplay == "Lorem ipsum dolor sit er elit lamet." ? "Lorem ipsum." : "Lorem ipsum dolor sit er elit lamet."
// autoLayoutLabel
autoLayoutLabel.text = textToDisplay
// springsAndStructsLabel
springsAndStructsLabel.text = textToDisplay
springsAndStructsLabel.sizeToFit()
// storyboardAutoLayoutLabel
storyboardAutoLayoutLabel.text = textToDisplay
}
}

- 6,026
- 4
- 43
- 51

- 89,880
- 29
- 256
- 218
-
The implementation is missing override for `textRect(forBounds:limitedToNumberOfLines:)` with call to super with bounds set to `UIEdgeInsetsInsetRect(bounds, padding)`, otherwise the text might get truncated - size calculation is not correct when the view size constrained (so `intrinsicContentSize` is not used). – Marián Černý Sep 18 '18 at 20:37
-
can you add properties so we can use it in storyboard and not programmatically? – user924 Apr 13 '19 at 21:05
Swift version of Recycled Steel's answer + intrinsizeContentSize()
.
It supports a more traditional style of setting insets for other view objects with insets while being able to set insets in Interface Builder, i.e. insets are set like so programmatically:
label.insets = UIEdgeInsetsMake(0, 0, 5, 0)
Please let me know if there are any bugs.
Swift 5
@IBInspectable var topInset: CGFloat = 0.0
@IBInspectable var leftInset: CGFloat = 0.0
@IBInspectable var bottomInset: CGFloat = 0.0
@IBInspectable var rightInset: CGFloat = 0.0
var insets: UIEdgeInsets {
get {
return UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
}
set {
topInset = newValue.top
leftInset = newValue.left
bottomInset = newValue.bottom
rightInset = newValue.right
}
}
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var adjSize = super.sizeThatFits(size)
adjSize.width += leftInset + rightInset
adjSize.height += topInset + bottomInset
return adjSize
}
override var intrinsicContentSize: CGSize {
var contentSize = super.intrinsicContentSize
contentSize.width += leftInset + rightInset
contentSize.height += topInset + bottomInset
return contentSize
}
Swift 4.2
@IBDesignable class InsetLabel: UILabel {
@IBInspectable var topInset: CGFloat = 0.0
@IBInspectable var leftInset: CGFloat = 0.0
@IBInspectable var bottomInset: CGFloat = 0.0
@IBInspectable var rightInset: CGFloat = 0.0
var insets: UIEdgeInsets {
get {
return UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)
}
set {
topInset = newValue.top
leftInset = newValue.left
bottomInset = newValue.bottom
rightInset = newValue.right
}
}
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: insets))
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var adjSize = super.sizeThatFits(size)
adjSize.width += leftInset + rightInset
adjSize.height += topInset + bottomInset
return adjSize
}
override var intrinsicContentSize: CGSize {
var contentSize = super.intrinsicContentSize
contentSize.width += leftInset + rightInset
contentSize.height += topInset + bottomInset
return contentSize
}
}
Swift 3
@IBDesignable class InsetLabel: UILabel {
@IBInspectable var topInset: CGFloat = 0.0
@IBInspectable var leftInset: CGFloat = 0.0
@IBInspectable var bottomInset: CGFloat = 0.0
@IBInspectable var rightInset: CGFloat = 0.0
var insets: UIEdgeInsets {
get {
return UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)
}
set {
topInset = newValue.top
leftInset = newValue.left
bottomInset = newValue.bottom
rightInset = newValue.right
}
}
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var adjSize = super.sizeThatFits(size)
adjSize.width += leftInset + rightInset
adjSize.height += topInset + bottomInset
return adjSize
}
override var intrinsicContentSize: CGSize {
var contentSize = super.intrinsicContentSize
contentSize.width += leftInset + rightInset
contentSize.height += topInset + bottomInset
return contentSize
}
}
Swift 2.2
@IBDesignable class InsetLabel: UILabel {
@IBInspectable var topInset: CGFloat = 0.0
@IBInspectable var leftInset: CGFloat = 0.0
@IBInspectable var bottomInset: CGFloat = 0.0
@IBInspectable var rightInset: CGFloat = 0.0
var insets: UIEdgeInsets {
get {
return UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)
}
set {
topInset = newValue.top
leftInset = newValue.left
bottomInset = newValue.bottom
rightInset = newValue.right
}
}
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))
}
override func sizeThatFits(size: CGSize) -> CGSize {
var adjSize = super.sizeThatFits(size)
adjSize.width += leftInset + rightInset
adjSize.height += topInset + bottomInset
return adjSize
}
override func intrinsicContentSize() -> CGSize {
var contentSize = super.intrinsicContentSize()
contentSize.width += leftInset + rightInset
contentSize.height += topInset + bottomInset
return contentSize
}
}
-
4I would suggest adding `invalidateIntrinsicContentSize()` and `setNeedsDisplay()` to the `insets` setter. – Archagon Oct 31 '16 at 00:33
-
-
label.insets = UIEdgeInsetsMake(0, 0, 5, 0) NOT label.inset = UIEdgeInsetsMake(0, 0, 5, 0) – coders Nov 25 '18 at 01:55
Edit: This is really old. There are better solutions above.
I ended up just adding some spaces to the text:
self.titleLabel.text = [NSString stringWithFormat:@" %@", self.titleLabel.text];
Ugly yet effective, and no subclassing required.
You can try "\t" as well. For a generic solution please refer to the accepted answer

- 13,273
- 1
- 38
- 44
-
3
-
5
-
-
Sadly had to downvote this as it's a trick that works until it doesn't. It's no different than a hacky function that returns a hardcoded value, which wouldn't typically pass the SO sniff test. – bitwit Oct 21 '19 at 19:41
-
-
@YarivNissim sorry, just a saying, not an actual test. I just mean I don't think the answer is up to typical Stack Overflow standards. Nice you've gotten many upvotes and it's helped people though. Cheers. – bitwit Oct 22 '19 at 00:06
-
This is totally wrong. If you can notice it if you try to add equal spaced before and after the text. You'll see that the spaces after the text will be cut off. – Matteo Gobbi Jul 19 '20 at 06:38
-
-
You can also solve this by initializing your UILabel with a custom frame.
CGRect initialFrame = CGRectMake(0, 0, 100, 100);
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 10, 0, 0);
CGRect paddedFrame = UIEdgeInsetsInsetRect(initialFrame, contentInsets);
self.label = [[UILabel alloc] initWithFrame:paddedFrame];
Nod to CGRect Tricks.

- 968
- 10
- 17
and an @IBDesignable that make it work with Interface Builder
Swift 4
//
// PaddedLabel.swift
// TrainCentric
//
// Created by Arsonik
// https://stackoverflow.com/a/33244365/337934
//
import UIKit
@IBDesignable
class PaddedLabel: UILabel {
@IBInspectable var inset:CGSize = CGSize(width: 0, height: 0)
var padding: UIEdgeInsets {
var hasText:Bool = false
if let t = self.text?.count, t > 0 {
hasText = true
}
else if let t = attributedText?.length, t > 0 {
hasText = true
}
return hasText ? UIEdgeInsets(top: inset.height, left: inset.width, bottom: inset.height, right: inset.width) : UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: padding))
}
override var intrinsicContentSize: CGSize {
let superContentSize = super.intrinsicContentSize
let p = padding
let width = superContentSize.width + p.left + p.right
let heigth = superContentSize.height + p.top + p.bottom
return CGSize(width: width, height: heigth)
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
let superSizeThatFits = super.sizeThatFits(size)
let p = padding
let width = superSizeThatFits.width + p.left + p.right
let heigth = superSizeThatFits.height + p.top + p.bottom
return CGSize(width: width, height: heigth)
}
}
Swift 2
@IBDesignable
class PaddedLabel: UILabel {
@IBInspectable var inset:CGSize = CGSize(width: 0, height: 0)
var padding: UIEdgeInsets {
var hasText:Bool = false
if let t = text?.length where t > 0 {
hasText = true
}
else if let t = attributedText?.length where t > 0 {
hasText = true
}
return hasText ? UIEdgeInsets(top: inset.height, left: inset.width, bottom: inset.height, right: inset.width) : UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, padding))
}
override func intrinsicContentSize() -> CGSize {
let superContentSize = super.intrinsicContentSize()
let p = padding
let width = superContentSize.width + p.left + p.right
let heigth = superContentSize.height + p.top + p.bottom
return CGSize(width: width, height: heigth)
}
override func sizeThatFits(size: CGSize) -> CGSize {
let superSizeThatFits = super.sizeThatFits(size)
let p = padding
let width = superSizeThatFits.width + p.left + p.right
let heigth = superSizeThatFits.height + p.top + p.bottom
return CGSize(width: width, height: heigth)
}
}
For Xamarin users (using Unified API):
class UIMarginLabel : UILabel
{
public UIMarginLabel()
{
}
public UIMarginLabel( CGRect frame ) : base( frame )
{
}
public UIEdgeInsets Insets { get; set; }
public override void DrawText( CGRect rect )
{
base.DrawText( Insets.InsetRect( rect ) );
}
}
And for those using the original MonoTouch API:
public class UIMarginLabel : UILabel
{
public UIEdgeInsets Insets { get; set; }
public UIMarginLabel() : base()
{
Insets = new UIEdgeInsets(0, 0, 0, 0);
}
public UIMarginLabel(RectangleF frame) : base(frame)
{
Insets = new UIEdgeInsets(0, 0, 0, 0);
}
public override void DrawText(RectangleF frame)
{
base.DrawText(new RectangleF(
frame.X + Insets.Left,
frame.Y + Insets.Top,
frame.Width - Insets.Left - Insets.Right,
frame.Height - Insets.Top - Insets.Bottom));
}
}

- 4,536
- 2
- 24
- 60
-
In the unified API example, RectangleF is used in the ctor; it should be CGRect in order to work – vividos May 25 '18 at 05:42
If you don't want to use an extra parent view to set the background, you can subclass UILabel and override textRectForBounds:limitedToNumberOfLines:
. I'd add a textEdgeInsets property or similar and then do
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds,textEdgeInsets) limitedToNumberOfLines:numberOfLines];
}
For robustness, you might also want to call [self setNeedsDisplay] in setTextEdgeInsets:, but I usually don't bother.

- 33,468
- 5
- 78
- 96
-
Note that, from the documentation, *"For this method to be called, there must be a prior call to the sizeToFit or sizeThatFits: method."* – mvds Jan 08 '11 at 21:46
-
2@mvds: That's fine: `textRectForBounds:limitedToNumberOfLines:` is being called, so it's up to whoever called it to ensure that there's been a prior call to `-sizeToFit`/`-sizeThatFits:`. – tc. Jan 20 '11 at 16:00
-
This doesn't appear to be working in Xcode 9.3/Swift 4.1/iOS 11.3. `textRectForBounds()` is being called and my edge insets are present, but the label doesn't have any of this padding. I am seeing odd values for the width and the height. This is a description of `bounds` from `textRectForBounds()`: `Printing description of bounds: ▿ (0.0, 0.0, 3.40282346638529e+38, 3.40282346638529e+38)`. The label is being created in `viewDidLoad()` in a view controller. – Evan R Apr 10 '18 at 19:40
-
1Adding this code to Brody Robertson's answer finally worked for me. Without overriding textRectForBounds:limitedToNumberOfLines: the last line of my string (a multiline attributed string converted from html) would be cut off. I am using Xcode 10.0 and iOS 12. – Alyoshak Dec 04 '18 at 17:31
To expand on the answer provided by Brody Robertson you can add the IB Designable bits. This means you can adjust the label from within Storyboard.
In your subclassed UILabel do
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface insetLabel : UILabel
@property (nonatomic, assign) IBInspectable CGFloat leftEdge;
@property (nonatomic, assign) IBInspectable CGFloat rightEdge;
@property (nonatomic, assign) IBInspectable CGFloat topEdge;
@property (nonatomic, assign) IBInspectable CGFloat bottomEdge;
@property (nonatomic, assign) UIEdgeInsets edgeInsets;
@end
Then do;
#import "insetLabel.h"
@implementation insetLabel
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.edgeInsets = UIEdgeInsetsMake(self.topEdge, self.leftEdge, self.bottomEdge, self.rightEdge);
}
return self;
}
- (void)drawTextInRect:(CGRect)rect
{
self.edgeInsets = UIEdgeInsetsMake(self.topEdge, self.leftEdge, self.bottomEdge, self.rightEdge);
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, self.edgeInsets)];
}
- (CGSize)intrinsicContentSize
{
CGSize size = [super intrinsicContentSize];
size.width += self.edgeInsets.left + self.edgeInsets.right;
size.height += self.edgeInsets.top + self.edgeInsets.bottom;
return size;
}
@end
EDIT
You should probably add a setter method for edgeInsets.

- 2,272
- 3
- 30
- 35
-
Please add this to your response so it actually works: - (void)awakeFromNib { self.edgeInsets = UIEdgeInsetsMake(self.topEdge, self.leftEdge, self.bottomEdge, self.rightEdge); } – Pauls Oct 01 '15 at 10:41
-
Autolayout should be fine, does it show up in Storyboard? Also I have just seen Pauls answer above, have you added the awakeFromNib? – Recycled Steel Apr 05 '16 at 09:41
-
Also, have you changed your Label class to the custom class? Third icon along in the top right. – Recycled Steel Apr 05 '16 at 09:44
-
@RecycledSteel I am having some problem, the above method works, but Its not resizing itself! I have set constraints on horizontally and vertically center. What should I do so that It gets update in size with the change in the Label Text – Jasmeet May 17 '16 at 08:50
Maybe later for the party, but the following just works. Just subclass UILabel.
#import "UITagLabel.h"
#define padding UIEdgeInsetsMake(5, 10, 5, 10)
@implementation UITagLabel
- (void)drawTextInRect:(CGRect)rect {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, padding)];
}
- (CGSize) intrinsicContentSize {
CGSize superContentSize = [super intrinsicContentSize];
CGFloat width = superContentSize.width + padding.left + padding.right;
CGFloat height = superContentSize.height + padding.top + padding.bottom;
return CGSizeMake(width, height);
}
- (CGSize) sizeThatFits:(CGSize)size {
CGSize superSizeThatFits = [super sizeThatFits:size];
CGFloat width = superSizeThatFits.width + padding.left + padding.right;
CGFloat height = superSizeThatFits.height + padding.top + padding.bottom;
return CGSizeMake(width, height);
}
@end

- 7,737
- 3
- 47
- 52
Here is a swift solution. Just add this custom class on the bottom of your file (or create a new file for it) and use MyLabel instead of UILabel when creating your label.
class MyLabel: UILabel{
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)))
}
}

- 10,348
- 5
- 39
- 36
-
This is the only thing I've found that actually works. Note you'll need to change the class of the Label in your storyboard if you're using storyboards. I had to set the top value to a negative number to push it up as high as I wanted as well. Thank you! – Trevor Turk Sep 09 '16 at 15:16
-
This is what you want. Great answer in a sea of taking the long way. – RegularExpression May 29 '17 at 05:12
-
1
I didn't find the suggestion to use UIButton
in the answers above. So I will try to prove that this is a good choice.
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
In my situation using UIButton
was the best solution because:
- I had a simple single-line text
- I didn't want to use
UIView
as a container forUILabel
(i.e. I wanted to simplify math calculations for Autolayout in my cell) - I didn't want to use
NSParagraphStyle
(becausetailIndent
works incorrect with Autolayout – width ofUILabel
is smaller than expected) - I didn't want to use
UITextView
(because of possible side effects) - I didn't want to subclass
UILabel
(less code fewer bugs)
That's why using the contentEdgeInsets
from UIButton
in my situation became the easiest way to add text margins.
Hope this will help someone.

- 6,024
- 2
- 26
- 31
If you're using autolayout in iOS 6+, you can do this by adjusting the intrinsicContentSize
in a subclass of UILabel
.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.textAlignment = NSTextAlignmentRight;
}
return self;
}
- (CGSize)intrinsicContentSize
{
CGSize size = [super intrinsicContentSize];
return CGSizeMake(size.width + 10.0, size.height);
}

- 10,667
- 11
- 45
- 66
blyabtroi's asnwer converted in Swift (No Subclassing required)
let style: NSMutableParagraphStyle = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
style.alignment = .Justified
style.firstLineHeadIndent = 10.0
style.headIndent = 10.0
style.tailIndent = -10.0
let attrText: NSAttributedString = NSAttributedString(string: title, attributes: [NSParagraphStyleAttributeName:style])
let label: UILabel = UILabel(frame: someFrame)
label.numberOfLines = 0
label.attributedText = attrText

- 243
- 2
- 9
Swift 4 version of blyabtroi solution
let leadingMargin: CGFloat = 10
let trailingMargin: CGFloat = 10
let style = NSMutableParagraphStyle()
style.alignment = .justified
style.firstLineHeadIndent = leadingMargin
style.headIndent = leadingMargin
style.tailIndent = trailingMargin
label.attributedText = NSAttributedString(string: "Label with margins",
attributes: [NSAttributedStringKey.paragraphStyle: style])

- 111
- 2
- 2
Instead of UILabel perhaps use https://github.com/mattt/TTTAttributedLabel
BITAttributedLabel *label = [BITAttributedLabel new];
label.font = font;
label.text = @"hello";
label.textInsets = UIEdgeInsetsMake(10, 10, 10, 10);
[label sizeToFit];

- 18,141
- 8
- 79
- 101

- 50,398
- 25
- 166
- 151
In Swift it solves like this.
class Label: UILabel {
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)))
}
}

- 1,338
- 13
- 13
This works correctly with multi-line labels:
class PaddedLabel: UILabel {
var verticalPadding: CGFloat = 0
var horizontalPadding: CGFloat = 0
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
}
override var intrinsicContentSize: CGSize {
get {
let textWidth = super.intrinsicContentSize.width - horizontalPadding * 2
let textHeight = sizeThatFits(CGSize(width: textWidth, height: .greatestFiniteMagnitude)).height
let width = textWidth + horizontalPadding * 2
let height = textHeight + verticalPadding * 2
return CGSize(width: frame.width, height: height)
}
}
}

- 34,062
- 40
- 136
- 186
A lot of the answers are missing the override of sizeThatFits. With this subclass you can just create the label, set the padding, and then say label.SizeToFit() and voila.
import UIKit
class UILabelEx : UILabel
{
var padding : UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, padding))
}
override func sizeThatFits(size: CGSize) -> CGSize
{
var adjSize = super.sizeThatFits(size)
adjSize.width += padding.left + padding.right
adjSize.height += padding.top + padding.bottom
return adjSize
}
}

- 1,710
- 14
- 20
Swift 3 & AutoLayout compatible version:
class InsetLabel: UILabel {
var insets = UIEdgeInsets()
convenience init(insets: UIEdgeInsets) {
self.init(frame: CGRect.zero)
self.insets = insets
}
convenience init(dx: CGFloat, dy: CGFloat) {
let insets = UIEdgeInsets(top: dy, left: dx, bottom: dy, right: dx)
self.init(insets: insets)
}
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
}
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
size.width += insets.left + insets.right
size.height += insets.top + insets.bottom
return size
}
}
This is the easiest solution I found for this:
Swift 4
class CustomLabel: UILabel{
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: UIEdgeInsets.init(top: 10, left: 10, bottom: 10, right: 10)))
}
}
Make sure you set your labels to the CustomLabel
class in code as well as in storyboard.

- 1,253
- 1
- 14
- 28
Xcode 6.1.1 Swift solution using a extension.
The file name could be something like "UILabel+AddInsetMargin.swift":
import UIKit
extension UILabel
{
public override func drawRect(rect: CGRect)
{
self.drawTextInRect(UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)))
}
}

- 3,733
- 1
- 35
- 36

- 4,178
- 4
- 24
- 36
-
Using extension to override an existing method in the main part of a class is not a good practice, except that `UILabel` does NOT and will NEVER write the method. – DawnSong Oct 12 '16 at 10:04
-
Whoa, hang on... you want to change the behaviour of every single UILabel? Potentially even for objects in frameworks you import, or other code you use? Someone else comes to use your code and can't figure out why a normal UILabel has an inset? Please, never ever do this. Only 'add' functionality with extensions, never 'change' functionality. – Jordan Smith Nov 11 '16 at 02:57
without subclassing and all that jazz.. i did this dynamically:
[cell.textLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[cell.textLabel constraintTrailingEqualTo:cell.contentView constant:-100];
the constraint part is just a simple code sugar wrapper (we have the same methods for adding a padding from top/bottom/left/right).. i'll open source the whole wrapper if i get enough love here:
- (id)constraintTrailingEqualTo:(UIView *)toView constant:(CGFloat)constant
{
NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:toView
attribute:NSLayoutAttributeTrailing
multiplier:1 constant:constant];
[toView addConstraint:cn];
return self;
}
(note i did this in the context of
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath;
you may have to call [self setNeedsLayout];
depending on your context.

- 23,101
- 16
- 132
- 246
#import "E_LabelWithPadding.h"
#define padding UIEdgeInsetsMake(2, 0, 2, 0)
#define padding1 UIEdgeInsetsMake(0, 0, 0, 0)
@implementation E_LabelWithPadding
- (void)drawTextInRect:(CGRect)rect {
if (![self.text isEqualToString:@""]) {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, padding)];
}else {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, padding1)];
}
}
- (CGSize) intrinsicContentSize {
if (![self.text isEqualToString:@""]) {
CGSize superContentSize = [super intrinsicContentSize];
CGFloat width = superContentSize.width + padding.left + padding.right;
CGFloat height = superContentSize.height + padding.top + padding.bottom;
return CGSizeMake(width, height);
}else {
CGSize superContentSize = [super intrinsicContentSize];
CGFloat width = superContentSize.width + padding1.left + padding1.right;
CGFloat height = superContentSize.height + padding1.top + padding1.bottom;
return CGSizeMake(width, height);
}
}
- (CGSize) sizeThatFits:(CGSize)size {
if (![self.text isEqualToString:@""]) {
CGSize superSizeThatFits = [super sizeThatFits:size];
CGFloat width = superSizeThatFits.width + padding.left + padding.right;
CGFloat height = superSizeThatFits.height + padding.top + padding.bottom;
return CGSizeMake(width, height);
}else {
CGSize superSizeThatFits = [super sizeThatFits:size];
CGFloat width = superSizeThatFits.width + padding1.left + padding1.right;
CGFloat height = superSizeThatFits.height + padding1.top + padding1.bottom;
return CGSizeMake(width, height);
}
}
@end

- 611
- 6
- 10
If label is created programmatically, padding can be calculated using the sizeThatFits method. If using more than one line, the text will be line broken at the max width value.
let text = UILabel()
let padding = 10
text.layer.cornerRadius = 5
text.layer.masksToBounds = true
text.text = "Hello"
text.font = UIFont(name: text.font.fontName, size: 18)
text.textAlignment = NSTextAlignment.center
text.numberOfLines = 1
let maxSize = CGSize(width: 100, height: 100)
var size = text.sizeThatFits(maxSize)
size.width = size.width + padding * 2
size.height = size.height + padding * 2
text.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: size)

- 816
- 10
- 12
I had solved it using xcode builder (but surely this could be achieved with swift using constraints):
Just create a UIView of the relevant size And add a child of type UILabel to that view
and there you go, you have padding :)

- 1,869
- 1
- 22
- 28
Maybe you could give this code a try
CGRect frame = btn.titleLabel.frame;
int indent = 20;
int inset = 20;
[btn.titleLabel setFrame:CGRectMake(frame.origin.x+inset,frame.origin.y,frame.size.width+indent,frame.size.height)];

- 1,662
- 20
- 39

- 25
- 1
-
1Use frame instead of *frame, use inset, not indent (typo). But the effect is nearly the same like moving the label 20 points to the right. That means, if I give a background color, the color is moved as well. So the solution is (at least for me) not useful. – Jojo.Lechelt Mar 15 '13 at 10:49
-
Note the question was about UILabels, UILabels do not contain a `titleLabel`, this fix is for UIButtons, just my two cents. – Dan Clarke Apr 23 '14 at 20:01
To get rid of vertical padding for a single line label I did:
// I have a category method setFrameHeight; you'll likely need to modify the frame.
[label setFrameHeight:font.pointSize];
OR, without the category, use:
CGRect frame = label.frame;
frame.size.height = font.pointSize;
label.frame = frame;

- 7,288
- 2
- 48
- 66
I think UILabel
class have no method for setting margin. Why you not set the position of Label at required place?
See below code:
UILabel *label = [[UILabel alloc] init];
label.text = @"This is label";
label.frame = CGRectMake(0,0,100,100);
if from interface builder then just position Label by following:
yourLabel.frame = CGRectMake(0,0,100,100);

- 26,549
- 8
- 62
- 79

- 1,039
- 14
- 32
Just add spaces to the left if it's a single line, more than 1 line will have 0 padding again.
[self.myLabel setText:[NSString stringWithFormat:@" %@", self.myShortString]];

- 12,795
- 4
- 39
- 60
You need to calculate UILabel size when you put insets. It can have different number of lines because of text alignment, line break mode.
override func drawText(in rect: CGRect) {
let size = self.sizeThatFits(UIEdgeInsetsInsetRect(rect, insets).size);
super.drawText(in: CGRect.init(origin: CGPoint.init(x: insets.left, y: insets.top), size: size));
}
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize;
if text == nil || text?.count == 0 {
return size;
}
size = self.sizeThatFits(UIEdgeInsetsInsetRect(CGRect.init(origin: CGPoint.zero, size: size), insets).size);
size.width += self.insets.left + self.insets.right;
size.height += self.insets.top + self.insets.bottom;
return size;
}

- 31
- 5
This is the easiest way I found. It works like a charm for me.
UIView *titleSection = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, 100)];
[titleSection addSubview:titleSection];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectInset(titleSection.frame, PADDING, 0)];
[titleSection addSubview:label];

- 980
- 1
- 14
- 26
A lot of these answers are complicated. In some cases, that's necessary. However, if you're reading this, your label has no left/right margin, and you just want a little padding, here's the whole solution:
Step 1: Add spaces at the end (literally, hit the spacebar a few times)
Step 2: Set the text alignment of the label to centered
Done

- 12,042
- 7
- 57
- 83
-
This is a terrible way to do it since if you change the text length, or font size, or font style, you'll be constantly updating the amount of spaces. Also, this means you can never Localise your app (different languages) since the text will be different. – kakubei Nov 28 '18 at 14:31
Set the label's textAlignment
property to NSTextAlignmentRight
and augment its width.

- 121,420
- 116
- 450
- 651
Don't code, Xcode !
Instead of using UILabel for this specific matter, I suggest you to take a look at UIButton. It gives, out of the box, the ability to set Content Insets (top, left, bottom, right) in the Size inspector. Set the desired margins, after that disable the button right in Xcode and done.

- 903
- 10
- 5
-
You're being downvoted because this question is about `UILabel` and you replied about `UIButton`. – Orlando Oct 19 '17 at 17:38
-
@Orlando I get it, no worries. However, for those looking for a solution that really works and with no overhead, they can try this and move on. – user1592811 Feb 01 '19 at 21:44