Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Changing baselineOffset moves text twice the distance expected

I am trying to vertically center the text in a UILabel with a minimum line height.
For that I am setting the attributedText with a paragraphStyle (to set the minimumLineHeight), and a baselineOffset (to center the text vertically).
I am calculating the baseline offset by subtracting the font lineHeight to the minimum line height, but I can only get the expected behaviour if I use half that value - which doesn't make sense to me because all these units are in points.
One can easily and quickly reproduce this by creating a new Single View App project:

  1. Drag a Label to the storyboard's main scene and use autolayout to center it vertically and horizontally in the container
  2. Change the label's background color (so it's easy to see the extra space inside the label)
  3. Create an outlet for the label in ViewController.swift
  4. In viewDidLoad(), add the following code:


// Get font line height
let fontLineHeight = label.font.lineHeight

// Set paragraph minimum line height to have an extra 10 points
let minimumLineHeight: CGFloat = fontLineHeight + 10.0
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.minimumLineHeight = minimumLineHeight

// Calculate baseline offset to move the text to the top of the label (which I'm expecting to be the extra 10 points)
let baselineOffset = minimumLineHeight - fontLineHeight

// Create and set the attributed text
let attributedText = NSAttributedString(string: "ÍÇ",
                                                attributes: [NSAttributedString.Key.paragraphStyle : paragraphStyle,
                                                             NSAttributedString.Key.baselineOffset : baselineOffset])
label.attributedText = attributedText


This only works if I use baselineOffset / 2.
Can anyone help me understand why?
Cheers

You want to center the text ? So, you need to move it half, isn't it ? Do draw a picture of this to analyze.

It probably has nothing to do with a point / pixel question.


Could you print the value of lineHeight, and tell what is the value you specified in font ?


You set:


let minimumLineHeight: CGFloat = fontLineHeight + 10.0
let baselineOffset = minimumLineHeight - fontLineHeight


So, baselineOffset = 10, exact ?


Why a fixed value ?

I'm experiencing the same thing.
In addition, this does not happen when I add a text attachment.
Besides minimumLineHeight and maximumLineHeight, I tried setting lineHeightMultiple, and a whole lot of text updating scenarios, and sometimes (!!!) it works as expected. But other times it needs to be halved again. Please someone shed a light on this. It sucks out the life from everything, so annoyingly frustrating.

On iOS 17+, baselineOffset works as expected.

For example, this code provides vertically centered text on the line.

let label = UILabel()
let lineHeight = 100.0
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.minimumLineHeight = lineHeight
paragraphStyle.maximumLineHeight = lineHeight
let baselineOffset = (lineHeight - label.font.lineHeight) / 2.0
label.attributedText = NSAttributedString(
    string: "Some text",
    attributes: [
        .paragraphStyle: paragraphStyle,
        .baselineOffset: baselineOffset
    ]
)

But on iOS 16 and lower, you have to divide the baseline offset twice: let baselineOffset = (lineHeight - label.font.lineHeight) / 2.0 / 2.0 to receive the same result.

Changing baselineOffset moves text twice the distance expected
 
 
Q