34

For some fonts, the built-in line spacing is unpleasantly large.

SwiftUI gives us the Text modifier .lineSpacing() to adjust the spacing between lines of text (also called the leading, unrelated to leading/trailing). Its value specifies the number of points of additional spacing to place between consecutive lines of text, so that .lineSpacing(0) results in no change. Unfortunately, it does not appear to respond to negative values; .lineSpacing(-10) yields the same result as lineSpacing(0).

Does anyone know of a way to reduce line spacing in SwiftUI without resorting to UIKit?

Ely
  • 8,259
  • 1
  • 54
  • 67
Anton
  • 2,512
  • 2
  • 20
  • 36
  • It is not a replacement, it is addition. Here is doc: "This value is always nonnegative. This value is included in the line fragment heights in the layout manager." – Asperi Sep 07 '20 at 15:08
  • 4
    Yes, we know the value is in addition to normal spacing, not a replacement for it, because .lineSpacing(0) is intended to have no effect. Thank you @Asperi - but still looking for a solution. – Anton Sep 07 '20 at 15:17
  • Alternatively, you could wrap `UILabel` to reduce line height: https://stackoverflow.com/a/68288238/7337835 – Toto Jul 08 '21 at 10:41
  • 2
    Thanks, @TotoMinai—but, as I mentioned in the original post, I'm looking for a SwiftUI solution that doesn't use UIKit. – Anton Jul 08 '21 at 14:52
  • I don't think it's possible to gain free control over negative line spacing in SwiftUI (as it ships in iOS 16 atm). My reasoning for this assessment:r as Text() seems to insist that the only compression you can make to the leading is down to Font.leading.tight – Alex Fringes Nov 23 '22 at 21:34
  • 2
    I found this when searching for the solution: https://openradar.appspot.com/FB9842474 It uses an undocumented (but maybe not private) `_lineHeightMultiple` modifier – tadelv Nov 28 '22 at 10:52

4 Answers4

3

Based on tadelv comment.

lineSpacing does not accept negative values, but you have a hidden API _lineHeightMultiple that works. It says it's deprecated but the suggested one does not exist!

var body: some View {
  let font = UIFont.systemFont(ofSize: 12)
  let fontLineHeight = font.lineHeight
  let desiredLineHeight = 24.0

  Text("text")
    .font(Font(font))
    ._lineHeightMultiple(desiredLineHeight / fontLineHeight)
}

Remember that using private apis could be rejected by App Store Review or break on future ios versions. Use at your own risk! (Damn Apple!)

kobuchi
  • 420
  • 5
  • 11
1

While I don't think it's possible to gain free control over negative line spacing in SwiftUI atm — as of Fall '22 all negative values create the same, only marginally tighter leading, no matter the value — you can reduce the leading of the Font itself, by applying .leading(.tight) to the Font. This did tighten a quick test example beyond what the negative value cap of .lineSpacing(-X) seems to achieve.

Iiro Alhonen
  • 352
  • 3
  • 19
Alex Fringes
  • 574
  • 3
  • 14
0

I think it works using negative values in some way.

Example

First image has lineSpacing set to -3, second set to 0.

-3 is the less value where I can see some effects.

Ribi
  • 1
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 06 '23 at 17:18
-4

You can split up the text in multiple lines and apply negative padding around each one like this:

Text("This is the first Line")
    .padding(-10)
Text("This is the second Line")
    .padding(-10)
  • 5
    Thanks, @user14952184. A good idea for the special case where you don't need any automatic text wrapping. Though not for the general case. – Anton Jul 08 '21 at 14:56
  • 2
    This leads to undesirable behavior with VoiceOver and DynamicType. – Warpling Sep 05 '22 at 13:17