Skip to content

fix(ios): force zero width for empty Text component#55472

Closed
Hector-Zhuang wants to merge 1 commit intofacebook:mainfrom
Hector-Zhuang:main
Closed

fix(ios): force zero width for empty Text component#55472
Hector-Zhuang wants to merge 1 commit intofacebook:mainfrom
Hector-Zhuang:main

Conversation

@Hector-Zhuang
Copy link
Copy Markdown
Contributor

Summary:

This PR fixes a layout regression in iO where empty components render with a non-zero width.

The Motivation: In commit(9fe20d4), the logic to add a placeholder "I" to empty strings was moved from ShadowNode to the platform-specific TextLayoutManager.

While the "I" placeholder provides the correct height, the measurement result also includes the width of the "I" character. This causes empty components to take up horizontal space.

Changelog:

[IOS] [FIXED] - Force zero width for empty Text components in Fabric to prevent ghost layout artifacts.

Test Plan:

Render a component with an empty string and a background color:

<Text style={{ backgroundColor: 'red' }} />

Before: A small red vertical sliver (the width of "I") is visible.
After: The component is invisible (0 width)

Related issue:

#55468

@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 Feb 9, 2026
@facebook-github-bot facebook-github-bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Feb 9, 2026
layoutContext:layoutContext
layoutConstraints:layoutConstraints];

if (originalAtributedString.isEmpty()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you leave a quick comment on why we do this

The “right fix” is for TextLayoutManager to use base attributes when the string is empty, instead of placeholder, like Android does, but that’s a good amount of work, so this workaround makes sense to me

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to check if originalAtributedString is empty. If it's empty, it should not be displayed, while attributedString has a placeholder "i"

@NickGerleman
Copy link
Copy Markdown
Contributor

Note, this is long time behavior of new architecture. Commit moving where placeholder was added so that Android wasn’t forced to have placeholder

@NickGerleman
Copy link
Copy Markdown
Contributor

@NickGerleman This is the function that adds a "i" placeholder to an empty string. This function is only used on iOS which doesn't affect Android.

https://github.dev/facebook/react-native/blob/5c49006a9eddf910fc0f525b3ba558def2b8e85e/packages/react-native/ReactCommon/react/renderer/attributedstring/PlaceholderAttributedString.h

https://github.dev/facebook/react-native/blob/5c49006a9eddf910fc0f525b3ba558def2b8e85e/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm

Please see 9fe20d4 for the history here.

It previously effected all platforms when the logic to insert I was in ShadowNode. I moved it out to each platform’s ViewManager, but on Android, to provide right height with no text, we need to resolve height of attributedstring without fragments. So the intention, is that text layout managers could measure empty strings using base text attributes of atteibutedstring.

Only made the changes for Android though, so logic here for placeholder was to keep previous behavior.

@meta-codesync
Copy link
Copy Markdown

meta-codesync bot commented Feb 22, 2026

@NickGerleman has imported this pull request. If you are a Meta employee, you can view this in D94011915.

@meta-codesync meta-codesync bot closed this in 537d2a6 Feb 25, 2026
@facebook-github-bot facebook-github-bot added the Merged This PR has been merged. label Feb 25, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync bot commented Feb 25, 2026

@NickGerleman merged this pull request in 537d2a6.

@react-native-bot
Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @Hector-Zhuang in 537d2a6

When will my fix make it into a release? | How to file a pick request?

zoontek pushed a commit to zoontek/react-native that referenced this pull request Mar 9, 2026
Summary:
This PR fixes a layout regression in iO where empty <Text /> components render with a non-zero width.

The Motivation: In commit(facebook@9fe20d4), the logic to add a placeholder "I" to empty strings was moved from ShadowNode to the platform-specific TextLayoutManager.

While the "I" placeholder provides the correct height, the measurement result also includes the width of the "I" character. This causes empty components to take up horizontal space.

## Changelog:

[IOS] [FIXED] - Force zero width for empty Text components in Fabric to prevent ghost layout artifacts.

Pull Request resolved: facebook#55472

Test Plan:
Render a component with an empty string and a background color:

```
<Text style={{ backgroundColor: 'red' }} />
```

Before: A small red vertical sliver (the width of "I") is visible.
After: The component is invisible (0 width)

## Related issue:

facebook#55468

Reviewed By: cipolleschi

Differential Revision: D94011915

Pulled By: NickGerleman

fbshipit-source-id: 8408dc43f06bd67e5938004148a4c9ebd3939864
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. Merged This PR has been merged. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants