Skip to content

Keep percentages in translateX/translateY string transforms - #59366

Open
camchis wants to merge 1 commit into
react:mainfrom
camchis:fix-transform-string-percentages
Open

camchis wants to merge 1 commit into
react:mainfrom
camchis:fix-transform-string-percentages

Conversation

@camchis

@camchis camchis commented Oct 22, 2026

Copy link
Copy Markdown

Summary:

processTransform drops the % unit when it parses translateX(...) or translateY(...) from a CSS transform string:

processTransform('translateX(10%)'); // [{translateX: 10}], expected [{translateX: '10%'}]

Native reads a bare number as points, so a view styled with transform: 'translateX(10%)' moves 10 points instead of 10% of its width. translate(10%, 20px) and the array form [{translateX: '10%'}] already keep the percentage, and so does the native CSS parser (enableNativeCSSParsing). Only the translateX/translateY branch of the JS string parser discards it.

The same parser also required a digit before the decimal point, so translateX(.5px) and matrix(.5, …) parsed .5 as 5. The array form and the native CSS parser both accept these. #57487 fixed the same problem in processTransformOrigin.

Changelog:

[GENERAL] [FIXED] - Keep percentages in translateX/translateY string transforms and parse numbers without a leading zero

Test Plan:

New tests fail without the fix and pass with it:

  • yarn fantom packages/react-native/Libraries/StyleSheet/__tests__/processTransform-itest.js: 19 passed. Without the fix, 2 fail: translateX(10%) gives {translateX: 10}, and translateX(.5px) gives {translateX: 5}.
  • yarn fantom packages/react-native/Libraries/Components/View/__tests__/View-itest.js: 228 passed. The new test renders a 200×50 <View> with transform: 'translateX(10%) translateY(20%)' and checks getBoundingClientRect(). Without the fix, the 2 enableNativeCSSParsing 🛑 variants fail with Expected 20 but received 10. The 2 ✅ variants already passed because the native parser handles it.
  • CSSTransformTest.cpp: added matrix_leading_dot, translate_x_leading_dot and translate_y_leading_dot to show the native parser already handles these inputs. I couldn't find an OSS runner for these tests, so I compiled the file against googletest 1.15.2 and the in-repo headers: 95 tests passed. Changing an expected value to 5.0f makes translate_x_leading_dot fail with Which is: 0.5, so the assertion is checking the parsed value.
  • yarn flow-check: 0 errors. ESLint --max-warnings 0 and Prettier on the changed JS files are clean, and node scripts/clang-format.js --check on the changed C++ file is clean.

Not run: RNTester on a device. The change is JS-only and covered by the Fantom layout test above.

`processTransform` dropped the `%` unit when parsing `translateX(...)` and
`translateY(...)` from a CSS transform string, so `'translateX(10%)'` became
`[{translateX: 10}]`, which native interprets as 10 points. `translate(...)`,
the array form, and the native CSS parser already preserve percentages.

The parser also required a digit before the decimal point, so
`translateX(.5px)` and `matrix(.5, ...)` parsed `.5` as `5`.

Adds Fantom coverage for the JS parser and a View layout test, plus native
CSS parser tests for numbers without a leading zero.
@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 22, 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 22, 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. 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