Repository navigation
Conversation
BackgroundPosition defaults top and left to 0, and the props parser only filled in bottom and right next to them. iOS reads top and left first, so `backgroundPosition: 'right 8px bottom 8px'` drew the image at the top left. Drop the default top when the value sets bottom, and the default left when it sets right. An explicit top or left still wins, as on Android.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary:
On iOS, a
backgroundPositionmeasured from the right or bottom edge is ignored. The image is drawn at the top left. Android draws it correctly.Root cause
BackgroundPosition()setstopandleftto0by default.processBackgroundPositionsends one edge per axis, for example{bottom: 8, right: 8}.fromRawValueinconversions.hfillsbottomandrightbut keeps the defaulttopandleft, so all four edges end up set.RCTBackgroundImageUtilsusestopandleftwhen they are set, sobottomandrightnever apply.Android's Props 2.0 path already works around this.
toDynamicinHostPlatformViewProps.cppprefers bottom and right, with the comment "JS sends one edge per axis, but the parser keeps the default top and left next to a bottom or right" (#59078). The bug has been there since #52283.Fix
The parser now drops the default
topwhen the value setsbottomwithout atop, and the defaultleftwhen it setsrightwithout aleft. Atoporleftgiven explicitly is kept and still wins, which matches Android'sBackgroundPosition.parse. The default constructor is unchanged, so a View with nobackgroundPositionstill positions at0 0.ReactCommon/react/renderer/components/view/conversions.htop/leftwhenbottom/rightis set without themReactCommon/react/renderer/components/view/tests/ConversionsTest.cppBehavior across platforms
toDynamic)top/leftnext tobottom/right(object form)Note
The only change in behavior is on iOS, for positions that use
rightorbottom, which now render as they do on Android and the web.Changelog:
[IOS] [FIXED] -
backgroundPositionnow honorsrightandbottomoffsetsTest Plan:
Automated checks
ConversionsTest.background_position_bottom_rightmain(top.has_value()andleft.has_value()are true), passes with the fixConversionsTest.background_position_top_left_next_to_bottom_rightreact_renderer_components_view_tests(Fantomreact-common-tests)node ./scripts/clang-format.js --checkon the changed filesyarn cxx-api-validate(Doxygen 1.16.1)Manual (RNTester, iPhone 17 simulator, iOS 27.0)
BackgroundImage › Gradient with Background Position, with two extra boxes added locally (
'right 8px bottom 8px'and[{bottom: 8, right: 8}], not part of this PR). The existingcenter,25% 75%andright bottomboxes look the same before and after.main)