Balancing Korean text in Signal’s message bubbles
Signal is an open source messenger, and its iOS app is developed in public. While reading Korean conversations in it, I noticed that message text sat slightly high inside its bubbles. The difference was small, but once I saw it, it appeared in almost every Korean message.
This post follows that detail from a visual impression to a measured cause, and then to a change that the Signal team merged into the app.
1. Turn an impression into numbers
A sense that something looks off is a starting point, not evidence. I measured the distance between the glyphs and the edges of the bubble. At the default text size, a short Korean message had about 9.5pt of space above the text and 12.5pt below it.
English text behaved differently depending on the words. “Okay sure” looked balanced, while “Hello” sat high in the same way Korean did. The difference was the descender, the part of letters such as g, p, and y that drops below the baseline. That pointed to the bottom of the text, not the top.
2. Read the rule the layout intends
Signal computes the insets of a message bubble from the message font. The rule aims for 11pt between the top of the capital letters and the top of the bubble, and 11pt between the baseline and the bottom. A comment in the code says that the descender should not count toward the bottom margin.
That is a sensible typographic rule. It treats the cap height and the baseline as the visible edges of a line, so the text should look centered regardless of which letters a message happens to contain.
3. Find where the extra space comes from
The rule assumed that the text label ends just below the descender. The label the app actually measured was taller. TextKit, the text layout system the app uses here, adds the font's leading below each line, about 1.7pt at the default size. The measured height is then rounded up to a whole point.
Together, those two details added roughly 2.7pt below the text. In English, descenders often fill that space and hide it. Hangul has no descenders, so the space stayed visible and the text looked lifted.
The rule was right. The measurement it relied on was slightly off, and Korean made the difference visible.
4. Keep the change narrow
Signal's contribution guide asks for bug fixes and generally declines changes to the user experience. That shaped the fix. I added a bottom inset that also subtracts the font's leading, and used it only when a bubble ends with body text.
Bubbles that end with a timestamp, a photo, or other content keep their existing layout. The change touches two files and adds sixteen lines. Keeping it small made it easier to review, and easier to explain as a correction to the existing rule.
5. Check it in the app
A correct formula can still produce a surprising screen, so I built the app from the main branch and from my change and compared the two. I ran both on an iPad Simulator linked to my account as a secondary device and sent the same messages to myself.
At the default text size, the space below Korean text went from 12.5pt to 10.5pt, while the space above stayed the same. I repeated the comparison with a smaller size, a much larger size, and an accessibility size, and checked photo captions, quoted replies, and link previews. The accessibility size stayed the same, as the formula predicted.
6. Separate the next question
One case is still unchanged. When a bubble shows a timestamp, Signal centers the timestamp on the baseline of the last line and measures the bottom padding from the timestamp. With Korean text, those bubbles still sit high.
That behavior follows a deliberate rule, and changing it would change how timestamps look in every language. I kept it out of this fix and treat it as a separate design question. In a local experiment, placing the timestamp on the same baseline as the text balanced those bubbles as well.
The Signal team merged the change in October 2026 and noted that it would go out with their next release. It is a small fix, but it reflects the part of design work I care about most: noticing a detail, finding the rule behind it, and making the correction concrete enough to review.