316

Is it possible to reduce the gap between text, when put in multiple lines in a UILabel? We can set the frame, font size and number of lines. I want to reduce the gap between the two lines in that label.

5
  • 1
    possible duplicate of How to increase a space between two lines in multiline label? Commented Sep 26, 2012 at 12:13
  • 2
    May I suggest that you accept one of the answers that is correct for iOS 6.0 and later? The currently accepted answer is out of date. Commented Oct 10, 2013 at 10:44
  • For each line use a new UILabel, then embed all labels in a StackView. Finally adjust the spacing of StackView. Remember to stack them vertically. Commented Jul 28, 2016 at 18:33
  • Refer the following link for solution in Swift 2. stackoverflow.com/a/39158698/6602495 Commented Aug 26, 2016 at 7:27
  • Refer to stackoverflow.com/a/44325650/342794 for storyboard tweak and other details. Commented Mar 12, 2018 at 20:04

21 Answers 21

430

In Xcode 6 you can do this in the storyboard:

enter image description here

Sign up to request clarification or add additional context in comments.

14 Comments

Take more advantages of storyboard!
@PaperThick have the same issue in 6.1.1. It "harlem shake" for few minutes. Doesn't know how to fix it :) Xcode Shaking
Is there a way to set custom fonts this way ? I can't seem to change that helvetica neue to any other font.
If you enable 'Attributed', and then open the file as source code you can edit the 'lineHeightMultiple' manually, and therefore bypass the Harlem Shake bug
@azdev for anyone still looking at this, I'm on longer getting the shakes in Xcode 7.3, but I think this is the first version where it hasn't been a problem
|
284

I thought about adding something new to this answer, so I don't feel as bad... Here is a Swift answer:

import Cocoa let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 40 let attrString = NSMutableAttributedString(string: "Swift Answer") attrString.addAttribute(.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length)) var tableViewCell = NSTableCellView() tableViewCell.textField.attributedStringValue = attrString 

"Short answer: you can't. To change the spacing between lines of text, you will have to subclass UILabel and roll your own drawTextInRect, or create multiple labels."

See: Set UILabel line spacing


This is a really old answer, and other have already addded the new and better way to handle this.. Please see the up to date answers provided below.

10 Comments

Since iOS 6.0, you can control it via NSAttributedString (also available in properties of UILable in Xcode's interface builder).
Interestingly, as near as I can tell, you can add extra spacing between the lines, but not reduce it via the NSParagraphStyle when using an NSAttributedString. (I may need to do more testing of the other modifyable properties, but the lineSpacing property only allows you to increase it.)
see my answer to see a way using NSAttributedString
@livingtech That is infuriating, and I believe you are correct. Have you found any workarounds?
Just to clarify something in this thread. If you want to shrink the line spacing set the line height to 1.0, and then setLineHeightMultiple to a lower value < 1.0, like: [paragraphStyle setLineHeightMultiple:0.8] or paragraphStyle.lineHeightMultiple = 0.8
|
109

Starting from iOS 6 you can set an attributed string to the UILabel. Check the following :

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:label.text]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineSpacing = spacing; [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, label.text.length)]; label.attributedText = attributedString; 

3 Comments

The attributedString must be an NSMutableAttributedString (NOT NSAttributedString)
The first line code should be NSMutableAttributedString *attributedString = [NSMutableAttributedString alloc]initWithString:@"sample text"];
The lineSpacing property of the NSMutableParagraphStyle is never negative, so the line height cannot be reduced with this approach. To answer the question, you have to use another property, see @d.ennis answer.
85

The solutions stated here didn't work for me. I found a slightly different way to do it with the iOS 6 NSAttributeString:

myLabel.numberOfLines = 0; NSString* string = @"String with line one. \n Line two. \n Line three."; NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; style.minimumLineHeight = 30.f; style.maximumLineHeight = 30.f; NSDictionary *attributtes = @{NSParagraphStyleAttributeName : style,}; myLabel.attributedText = [[NSAttributedString alloc] initWithString:string attributes:attributtes]; [myLabel sizeToFit]; 

3 Comments

Line height is font size dependent. Line spacing is just that, line spacing. You may get things to work out by just setting min/max line height, but that's only because the current font sizes you're using aren't greater than the line height boundaries. Per the documentation: "... glyphs and graphics exceeding this height will overlap neighboring lines ... Although this limit applies to the line itself, line spacing adds extra space between adjacent lines."
+1, If you want to reduce the spacing between lines, this is what you want to do. The real line spacing is most likely 0 by default, this is why people report you can only increase it. The problem with spacing being too big comes from the line height being too big, this is why this will get the job done 99% of the time.
This is the only answer I could find that uses the actual line height value (instead of a ratio) common to design applications such as Photoshop, Sketch, CSS, etc.
43

From Interface Builder (Storyboard/XIB):

enter image description here

Programmatically:

SWift 4

Using label extension

extension UILabel { // Pass value for any one of both parameters and see result func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) { guard let labelText = self.text else { return } let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineSpacing paragraphStyle.lineHeightMultiple = lineHeightMultiple let attributedString:NSMutableAttributedString if let labelattributedText = self.attributedText { attributedString = NSMutableAttributedString(attributedString: labelattributedText) } else { attributedString = NSMutableAttributedString(string: labelText) } // Line spacing attribute attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length)) self.attributedText = attributedString } } 

Now call extension function

let label = UILabel() let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel" // Pass value for any one argument - lineSpacing or lineHeightMultiple label.setLineSpacing(lineSpacing: 2.0) . // try values 1.0 to 5.0 // or try lineHeightMultiple //label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0 

Or using label instance (Just copy & execute this code to see result)

let label = UILabel() let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel" let attrString = NSMutableAttributedString(string: stringValue) var style = NSMutableParagraphStyle() style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48 style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40 // Line spacing attribute attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count)) // Character spacing attribute attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length)) label.attributedText = attrString 

Swift 3

let label = UILabel() let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel" let attrString = NSMutableAttributedString(string: stringValue) var style = NSMutableParagraphStyle() style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48 style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40 attrString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSRange(location: 0, length: stringValue.characters.count)) label.attributedText = attrString 

2 Comments

Add the line " paragraphStyle.alignment = self.textAlignment" to keep the original alignment . Otherwise, the text will be left aligned.
For anyone loosing ellipsis on large texts, then use: paragraphStyle.lineBreakMode = .byTruncatingTail
40

I've made this simple extension that works very well for me:

extension UILabel { func setLineHeight(lineHeight: CGFloat) { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 1.0 paragraphStyle.lineHeightMultiple = lineHeight paragraphStyle.alignment = self.textAlignment let attrString = NSMutableAttributedString() if (self.attributedText != nil) { attrString.append( self.attributedText!) } else { attrString.append( NSMutableAttributedString(string: self.text!)) attrString.addAttribute(NSAttributedStringKey.font, value: self.font, range: NSMakeRange(0, attrString.length)) } attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length)) self.attributedText = attrString } } 

Copy this in a file, so then you can use it like this

myLabel.setLineHeight(0.7) 

8 Comments

remember if you doing this while you are also using Storyboard for this label, then be sure to set your label's lines to 0
Why don't you just directly set the lineSpacing and forget about setting lineHeightMultiple?
Because the key to reduce the line height is 'lineHeightMultiple', no lineSpacing
say you want your line height to be 1.4, why can't you just write .lineSpacing = 1.4 and forget all about .lineHeightMultiple...
Hah! I tried, and I didn't work, but I wonder why I don't see other answers here not using your mechanism, I mean they just directly set the lineSpacing. See the accepted answer...
|
19

There's an alternative answer now in iOS 6, which is to set attributedText on the label, using an NSAttributedString with the appropriate paragraph styles. See this stack overflow answer for details on line height with NSAttributedString:

Core Text - NSAttributedString line height done right?

Comments

16

Here is a class that subclass UILabel to have line-height property : https://github.com/LemonCake/MSLabel

2 Comments

This worked for me, thanks. I also tried to use MTLabel, but this one was better.
Does anyone know if MSLabel supports the '\n' character?
15

In Swift and as a function, inspired by DarkDust

// Usage: setTextWithLineSpacing(myEpicUILabel,text:"Hello",lineSpacing:20) func setTextWithLineSpacing(label:UILabel,text:String,lineSpacing:CGFloat) { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineSpacing let attrString = NSMutableAttributedString(string: text) attrString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length)) label.attributedText = attrString } 

Comments

13

According @Mike 's Answer, reducing the lineHeightMultiple is the key point. Example below, it work well for me:

NSString* text = label.text; CGFloat textWidth = [text sizeWithAttributes:@{NSFontAttributeName: label.font}].width; if (textWidth > label.frame.size.width) { NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init]; paragraph.alignment = NSTextAlignmentCenter; paragraph.lineSpacing = 1.0f; paragraph.lineHeightMultiple = 0.75; // Reduce this value !!! NSMutableAttributedString* attrText = [[NSMutableAttributedString alloc] initWithString:text]; [attrText addAttribute:NSParagraphStyleAttributeName value:paragraph range:NSMakeRange(0, text.length)]; label.attributedText = attrText; } 

Comments

9

SWIFT 3 useful extension for set space between lines more easily :)

extension UILabel { func setLineHeight(lineHeight: CGFloat) { let text = self.text if let text = text { let attributeString = NSMutableAttributedString(string: text) let style = NSMutableParagraphStyle() style.lineSpacing = lineHeight attributeString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSMakeRange(0, text.characters.count)) self.attributedText = attributeString } } } 

Comments

5

I've found a way where you can set the real line height (not a factor) and it even renders live in Interface Builder. Just follow the instructions below. Code is written in Swift 4.


Step #1: Create a file named DesignableLabel.swift and insert the following code:

import UIKit @IBDesignable class DesignableLabel: UILabel { @IBInspectable var lineHeight: CGFloat = 20 { didSet { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.minimumLineHeight = lineHeight paragraphStyle.maximumLineHeight = lineHeight paragraphStyle.alignment = self.textAlignment let attrString = NSMutableAttributedString(string: text!) attrString.addAttribute(NSAttributedStringKey.font, value: font, range: NSRange(location: 0, length: attrString.length)) attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attrString.length)) attributedText = attrString } } } 

Step #2: Place a UILabel into a Storyboard/XIB and set its class to DesignableLabel. Wait for your project to build (build must succeed!).

Specifying the class to your UILabel


Step 3: Now you should see a new property in the properties pane named "Line Height". Just set the value you like and you should see the results immediately!

Set Line Height in properties

1 Comment

You don't need a subclass to do this. You can do it in a UILabel Extension and still add @IBInspectable - which is important if you already have a UILabel subclass and you don't want a weird class hierarchy
3

Here is a subclass of UILabel that sets lineHeightMultiple and makes sure the intrinsic height is large enough to not cut off text.

@IBDesignable class Label: UILabel { override var intrinsicContentSize: CGSize { var size = super.intrinsicContentSize let padding = (1.0 - lineHeightMultiple) * font.pointSize size.height += padding return size } override var text: String? { didSet { updateAttributedText() } } @IBInspectable var lineHeightMultiple: CGFloat = 1.0 { didSet { updateAttributedText() } } private func updateAttributedText() { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineHeightMultiple = lineHeightMultiple attributedText = NSAttributedString(string: text ?? "", attributes: [ .font: font, .paragraphStyle: paragraphStyle, .foregroundColor: textColor ]) invalidateIntrinsicContentSize() } } 

3 Comments

extra padding must be (lineHeightMultiple - 1.0) * font.pointSize, right?
The code above as-is seemed to work for me. But maybe you are right. Did you try your change? @PavelAlexeev
No, I stick with lineSpacing instead of lineHeightMultiple :)
3

Swift 3 extension:

import UIKit extension UILabel { func setTextWithLineSpacing(text: String, lineHeightMultiply: CGFloat = 1.3) { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineHeightMultiple = lineHeightMultiply paragraphStyle.alignment = .center let attributedString = NSMutableAttributedString(string: text) attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length)) self.attributedText = attributedString } } 

1 Comment

This solution works for me i just change paragraphStyle.alignment = .center to paragraphStyle.lineBreakMode = .byTruncatingTail paragraphStyle.baseWritingDirection = NSParagraphStyle.defaultWritingDirection(forLanguage: GeneralMethods.getSelectedLanguage().stringValue) and its automatically adopt direction according to selected language.
1

In Swift 2.0...

Add an extension:

extension UIView { func attributesWithLineHeight(font: String, color: UIColor, fontSize: CGFloat, kern: Double, lineHeightMultiple: CGFloat) -> [String: NSObject] { let titleParagraphStyle = NSMutableParagraphStyle() titleParagraphStyle.lineHeightMultiple = lineHeightMultiple let attribute = [ NSForegroundColorAttributeName: color, NSKernAttributeName: kern, NSFontAttributeName : UIFont(name: font, size: fontSize)!, NSParagraphStyleAttributeName: titleParagraphStyle ] return attribute } } 

Now, just set your UILabel as attributedText:

self.label.attributedText = NSMutableAttributedString(string: "SwiftExample", attributes: attributesWithLineHeight("SourceSans-Regular", color: UIColor.whiteColor(), fontSize: 20, kern: 2.0, lineHeightMultiple: 0.5)) 

Obviously, I added a bunch of parameters that you may not need. Play around -- feel free to rewrite the method -- I was looking for this on a bunch of different answers so figured I'd post the whole extension in case it helps someone out there... -rab

Comments

1

Swift3 - In a UITextView or UILabel extension, add this function:

I added some code to keep the current attributed text if you are already using attributed strings with the view (instead of overwriting them).

func setLineHeight(_ lineHeight: CGFloat) { guard let text = self.text, let font = self.font else { return } let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 1.0 paragraphStyle.lineHeightMultiple = lineHeight paragraphStyle.alignment = self.textAlignment var attrString:NSMutableAttributedString if let attributed = self.attributedText { attrString = NSMutableAttributedString(attributedString: attributed) } else { attrString = NSMutableAttributedString(string: text) attrString.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, attrString.length)) } attrString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSMakeRange(0, attrString.length)) self.attributedText = attrString } 

Comments

1

Another answer... If you're passing the string programmatically, you need to pass a attributed string instead a regular string and change it's style.(iOS10)

NSMutableAttributedString * attrString = [[NSMutableAttributedString alloc] initWithString:@"Your \nregular \nstring"]; NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; [style setLineSpacing:4]; [attrString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, attrString.length)]; _label.attributedText = attrString; 

Comments

1

This should help with it. You can then assign your label to this custom class within the storyboard and use it's parameters directly within the properties:

open class SpacingLabel : UILabel { @IBInspectable open var lineHeight:CGFloat = 1 { didSet { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 1.0 paragraphStyle.lineHeightMultiple = self.lineHeight paragraphStyle.alignment = self.textAlignment let attrString = NSMutableAttributedString(string: self.text!) attrString.addAttribute(NSAttributedStringKey.font, value: self.font, range: NSMakeRange(0, attrString.length)) attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attrString.length)) self.attributedText = attrString } } } 

2 Comments

This should help with it. You can then assign your label to this custom class within the storyboard and use it's parameters directly within the properties.
please don't put content related to your answer in the comments. your answer should be helpful without having to read through the comments
1

Swift 4 label extension. Creating NSMutableAttributedString before passing into function in case there are extra attributes required for the attributed text.

extension UILabel { func setLineHeightMultiple(to height: CGFloat, withAttributedText attributedText: NSMutableAttributedString) { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 1.0 paragraphStyle.lineHeightMultiple = height paragraphStyle.alignment = textAlignment attributedText.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedText.length - 1)) self.attributedText = attributedText } } 

Comments

0

This code worked for me (ios 7 & ios 8 for sure).

_label.numberOfLines=2; _label.textColor=[UIColor whiteColor]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineHeightMultiple=0.5; paragraphStyle.alignment = NSTextAlignmentCenter; paragraphStyle.lineSpacing = 1.0; NSDictionary *nameAttributes=@{ NSParagraphStyleAttributeName : paragraphStyle, NSBaselineOffsetAttributeName:@2.0 }; NSAttributedString *string=[[NSAttributedString alloc] initWithString:@"22m\nago" attributes:nameAttributes]; _label.attributedText=string; 

Comments

-1

Here is my solution in swift. The subclass should work for both attributedText and text property and for characterSpacing + lineSpacing. It retains the spacing if a new string or attributedString is set.

open class UHBCustomLabel : UILabel { @IBInspectable open var characterSpacing:CGFloat = 1 { didSet { updateWithSpacing() } } @IBInspectable open var lines_spacing:CGFloat = -1 { didSet { updateWithSpacing() } } open override var text: String? { set { super.text = newValue updateWithSpacing() } get { return super.text } } open override var attributedText: NSAttributedString? { set { super.attributedText = newValue updateWithSpacing() } get { return super.attributedText } } func updateWithSpacing() { let attributedString = self.attributedText == nil ? NSMutableAttributedString(string: self.text ?? "") : NSMutableAttributedString(attributedString: attributedText!) attributedString.addAttribute(NSKernAttributeName, value: self.characterSpacing, range: NSRange(location: 0, length: attributedString.length)) if lines_spacing >= 0 { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lines_spacing paragraphStyle.alignment = textAlignment attributedString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSMakeRange(0, attributedString.length)) } super.attributedText = attributedString } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.