Skip to content

iOS Fabric: wrapping <Text> with lineHeight clips the last line's final word #58156

Description

@orangebibleapp-create

Description

On the iOS New Architecture (Fabric), a wrapping <Text> that has an explicit lineHeight set mis-measures the width of its last line and clips the final word (or last few characters) off the right edge. The same tree renders correctly on Android, and correctly on iOS with the legacy renderer.

Because the mis-measurement is sub-pixel and width/font-size/device dependent, it manifests as a knife-edge: the clip only appears for certain line contents at certain widths/font sizes, so it's easy to miss in testing and shows up as user reports of "the last word is cut off" on some devices but not others.

This is the same underlying defect as #53092 (closed only because a stale-bot auto-closed it after 180 days — not because it was fixed) and the abandoned/​unmerged PR #53341. Filing a fresh, self-contained report since the original is closed and the bug still reproduces on current releases.

Steps to reproduce

  1. New Architecture enabled, iOS.
  2. Render a <Text> with an explicit lineHeight that is wide enough to wrap to several lines, where the last line is nearly full (so the final word sits close to the right edge). Nested child <Text> spans (as in a paragraph made of multiple styled runs) make it more reliable.
  3. Observe the last word/characters of the block clipped off the right edge. Remove lineHeight → renders correctly (but you lose the desired leading).
import { Text, View } from 'react-native';

export default function Repro() {
  return (
    <View style={{ padding: 20 }}>
      <Text style={{ fontSize: 24, lineHeight: 36 }}>
        <Text>Then he is to take the bull outside the camp and burn it, </Text>
        <Text>just as he burned the first bull. It is the sin offering for the assembly.</Text>
      </Text>
    </View>
  );
}

The trailing "assembly." clips on iOS Fabric; correct on Android / iOS Paper.

Workaround

Append a throwaway trailing line (a newline + zero-width space) as the last child of the wrapping <Text>. The mis-measured "last line" is then the empty one, so the real last line of content measures and wraps correctly — while the desired lineHeight is preserved:

<Text style={{ fontSize: 24, lineHeight: 36 }}>
  {/* ...content... */}
  {'\n​'}
</Text>

This is stable in practice (it doesn't depend on tuning width/height per device the way the earlier hidden-character workarounds in #53092 did), at the cost of a small amount of trailing vertical space.

React Native Version

0.83.6

Affected Platforms

Runtime - iOS (New Architecture / Fabric). Android and iOS legacy renderer unaffected.

Environment

  • React Native 0.83.6, Hermes, New Architecture enabled
  • Expo SDK 55
  • Reproduced on iOS 26 simulators (iPhone 16 / 17 Pro) and reported by users on physical devices

Additional notes

Refs #53092, #53341. The last human comment on #53092 (2025-09) reports the same behavior on Android in some configurations and notes the then-current workarounds were unstable across line height / font size / screen density; the trailing-empty-line approach above avoids that instability.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs: Author FeedbackNeeds: ReproThis issue could be improved with a clear list of steps to reproduce the issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions