Skip to content

Place views nested in Text on the baseline on iOS - #59551

Open
mozzius wants to merge 1 commit into
react:mainfrom
mozzius:inline-view-baseline
Open

mozzius wants to merge 1 commit into
react:mainfrom
mozzius:inline-view-baseline

Conversation

@mozzius

@mozzius mozzius commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Summary:

Fixes #59549.

On iOS, a View nested in a Text is placed below the text baseline, while Android puts its bottom exactly on the baseline. _measureTextStorage: puts the attachment's bottom at the bottom of its glyph rect plus font.descender, where font is the font on the attachment's own run. That's only the baseline in a narrow case:

  • React Native never gives the attachment's run a font, so NSTextStorage fills in its default, 12pt Helvetica (descender −2.76), whatever the surrounding text is.
  • A lineHeight taller than the font raises the glyphs by (lineHeight - font.lineHeight) / 2 (RCTApplyBaselineOffset). The line bottom plus a descender doesn't include that.
  • With mixed font sizes on a line, the line's descent comes from its largest font.

So the view sits |line descender| + baseline offset - 2.76 below the baseline: 0.86pt for 15pt system text, 3.91pt with lineHeight: 24, and 14.15pt for 24pt text with lineHeight: 36 at the first accessibility text size. The current formula came in with #53341 in 0.82, to fix #53092; on 0.81 the same screen puts the view on the baseline in all but the #53092 case.

This places the attachment on the baseline TextKit actually laid its line out with: the line fragment's origin plus the attachment glyph's location within it. That includes the baseline offset and the line's largest font, and it's the baseline onTextLayout reports for each line. It also fixes the #53092 case, where the view is taller than the line's ascent.

Compared with the open PRs for this:

Changelog:

[IOS] [FIXED] - Views nested in Text sit on the text baseline instead of below it

Test Plan:

Reproducer: https://github.com/mozzius/inline-view-baseline-repro (RN 0.88.0, with this change as a patch behind a runtime stock/fixed switch). Each row is a Text with a nested blue View; the red hairline is the line's baseline from onTextLayout.

View bottom minus baseline, in points (positive is below), on an iPhone 17 Pro simulator (iOS 26.5):

Sample Stock Stock, Accessibility Medium This PR (both sizes)
15 / no lineHeight +0.67 +3.67 0
15 / 15 +1.00 +3.67 0
15 / 20 +2.00 +5.67 0
15 / 24 +4.00 +9.00 0
24 / no lineHeight +3.00 +7.67 0
24 / 28 +3.00 +7.67 0
24 / 36 +6.67 +14.33 0
The #53092 case (14 bold / 16.8, 54×20 view) +0.67 +3.33 0
15pt text with a nested 24pt word +3.00 +7.67 0
Wrapped 15 / 24, view mid-paragraph +4.00 +9.00 0

The letters sit exactly on the hairline in every screenshot. The repro's README has the logs, the formula-vs-measurement tables, and the 0.81.6 and Android comparisons.

Stock This PR Android

We also ship this as a patch in the Bluesky app (RN 0.88), where it moved verification badges inside display names from 2.2pt below centre (5–7pt at the accessibility text sizes) to within 0.2pt (bluesky-social/social-app#12229).

🤖 Generated with Claude Code

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 27, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 27, 2026
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Visual regression

1 visual difference(s) at aae21afeeb89. Visual differences need maintainer approval. Review the report, then apply visual-change-approved.

android: no capture

ios scroll-view/horizontal-scroll-to/end: Changed, 69504 px (18.123%)

diff

Expected and Captured
Expected Captured
expected captured

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mozzius
mozzius force-pushed the inline-view-baseline branch from cfd4309 to aae21af Compare October 27, 2026 21:56
@mozzius

mozzius commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

I am fairly certain the visual regression test is a flake, but I'll try and confirm locally

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

1 participant