Skip to content

Skip the clear background attribute on iOS Text - #59207

Open
hryhoriiK97 wants to merge 1 commit into
react:mainfrom
hryhoriiK97:ios-text-skip-clear-background
Open

hryhoriiK97 wants to merge 1 commit into
react:mainfrom
hryhoriiK97:ios-text-skip-clear-background

Conversation

@hryhoriiK97

@hryhoriiK97 hryhoriiK97 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

RCTNSTextAttributesFromTextAttributes (ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm) builds the attributes TextKit draws each text fragment with.

Current behavior. It sets NSBackgroundColorAttributeName whenever textAttributes.backgroundColor is set or opacity is set. TextAttributes::defaultTextAttributes() sets backgroundColor to clearColor(), so every fragment of every <Text> gets a transparent background attribute, including text that never asked for a background. On every draw, NSLayoutManager then computes the rects of each run carrying that attribute and fills them with the clear color, which changes no pixels. In a Time Profiler trace of mounting 1000 labels on a device, this background pass was about a third of -[RCTTextLayoutManager drawAttributedString:...].

With this change. The attribute is set only when the background color is set and is not clearColor(). A clear background draws nothing, so the pixels are the same, and TextKit skips the background pass for text without a background. Text with a visible background color keeps the attribute as before, including with opacity. A nested <Text> with backgroundColor: 'transparent' inside a parent with a background renders the same, since each fragment carries its own attributes. The other reader of the attribute, processTruncatedAttributedText: in RCTTextLayoutManager, already handles it being absent.

Changelog:

[IOS] [CHANGED] - Text without a background color no longer draws a transparent background

Test Plan:

  • node scripts/clang-format.js --check on the changed file passes.
  • RNTester built with xcodebuild in Release and run on a physical iPhone 15 Pro (iOS 26.6.1).
  • Same output.
    • Screenshots of a list of 1000 labels in bordered cards, with shadow props and with boxShadow, are byte-identical in the list area with and without the change.
    • In the RNTester Text examples (25 screens of scrolling, including text with background colors, borders and nested text), static screens are byte-identical with and without the change once scroll positions are aligned. Where a screen landed a few points off, only the anti-aliased corners of rounded Views differ, by at most 5 levels, and the same screen captured at the same position is byte-identical. Screens with animated content differ between two runs without the change as well.
  • Measurement. RNTester Playground mounting items in a ScrollView, each a View wrapping a Text, with three contents (plain, bordered card with shadow props, and the card with boxShadow). Timed: the total time in -[RCTParagraphTextView drawRect:] in the display pass after each mount, and the time from the end of the mount to the CoreAnimation commit, which contains that pass. The two arms are the same binary with the change switched by an environment variable. 20 items were mounted ten times per content per launch, in the order before, after, after, before. 1000 items were mounted five times per content per launch, in two series in opposite orders (before, after, after, before, then after, before, before, after), which gave the same numbers. The presses were driven by Argent on the physical iPhone. iPhone 15 Pro, Release, medians:
20 labels, 62–63 mounts per arm before this PR change
text drawing per mount 5.06 ms 3.58 ms −29%
end of mount to CoreAnimation commit 4.4 ms 3.4 ms −23%
1000 labels, 60 mounts per arm before this PR change
text drawing per mount 58.1 ms 38.2 ms −34%
end of mount to CoreAnimation commit 124.4 ms 93.6 ms −25%

🤖 Generated with Claude Code

TextAttributes default backgroundColor to clearColor(), so every fragment of
every Text got NSBackgroundColorAttributeName set to a transparent color, and
TextKit computed and filled the background rects of each run on every draw
without changing any pixel. Set the attribute only for a background color that
isn't clear.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@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 19, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Oct 19, 2026

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. p: Software Mansion Partner: Software Mansion Partner 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.

1 participant