About density-independent pixels
A dp is a logical UI unit. Vega maps it to physical pixels using the display scale factor:width: 100 as 100 physical pixels. After migration, the same value means 100 dp. Vega draws it as 200 physical pixels at a scale factor of 2, or 266 physical pixels at a scale factor of 2.66. This is the main layout impact to evaluate.
The Vega canvas reference size is 960x540 dp, which is a scale factor of 2 on a 1080p display.
What the unit change covers
RN 0.83 applies the dp mapping across the full UI path:- Vega scales the final drawing canvas and the damage regions.
- Window sizes and positions cross the graphics boundary in physical pixels, but stay in dp in your app code.
- Pointer, touch, resize, window-position, and occlusion events arrive back in React Native as dp.
- Child windows, pop-ups, modals, texture-cached layers, and virtual surfaces use the same scale.
DimensionsanduseWindowDimensions()report logical dimensions.PixelRatio.get()reports the ratio of physical pixels to dp.
What the unit change doesn’t cover
Two things keep their existing behavior:- Bitmap data. dp rendering doesn’t scale bitmap data or change image metadata. Image decoders, bitmaps, pixmaps, and textures continue to use physical pixel dimensions.
- Font scaling. dp rendering doesn’t replace accessibility font scaling. Keep using React Native text APIs and
fontScalefor user-selected text size.
PixelRatio and the DeviceInfo TurboModule
PixelRatio is a React Native JavaScript utility, not a standalone TurboModule. PixelRatio.get() reads Dimensions.get('window').scale. The native DeviceInfo TurboModule supplies width, height, scale, and fontScale to Dimensions.
In RN 0.83, DeviceInfo reports logical window dimensions along with the active physical-pixel-to-dp scale. It also publishes per-surface dimension updates through didUpdateDimensions.
Why Vega uses density-independent pixels
React Native on Android and iOS uses logical units by default. Vega adopts the same default coordinate model for RN 0.83 apps, so geometry behaves the same way on all three targets. One unit contract now covers standard React Native components, custom native components, TurboModules, third-party libraries, window APIs, rendering, and input events. Your app describes UI geometry in logical units, and Vega converts that geometry at the graphics boundary. UI proportions stay stable across devices with different canvas resolutions, and Scalable UI can select a higher-resolution canvas without a separate pixel layout.Changes in your app
The following table maps common RN 0.72 patterns to their RN 0.83 behavior.Convert pixel-tuned values
Numeric length values are dp in RN 0.83. Convert the values you tuned as physical pixels, using the scale factor of your pre-migration baseline:Replace fixed screen dimensions
Hardcoded screen constants no longer describe the logical viewport. Read the dimensions at runtime instead.useWindowDimensions() returns logical dimensions. Don’t convert them to physical pixels before you assign React Native styles.
Use logical input coordinates
RN 0.83 reports pointer and touch coordinates in dp:Keep custom native interfaces in dp
Define custom component and TurboModule geometry as dp at the React Native boundary.widthDp and targetWidthPx.
Handle images
Image layout and image data use different units:<Image style={{width, height}}>uses dp.- Source bitmap dimensions, decoded image dimensions, row bytes, and texture dimensions use physical pixels.
- When React Native supplies a preferred logical decode size, the Vega image pipeline multiplies it by the active scale factor before decoding. Don’t multiply the
<Image>style or the preferred layout size in your own code. - A source needs enough physical pixels for its rendered dp size. An image rendered at 320x180 dp at a scale factor of 2 needs at least 640x360 source pixels to avoid upscaling.
Local assets
Provide density variants in the same directory. Metro and React Native select the asset that matches the active density.@3x data. React Native selects the next higher-resolution asset instead of upscaling a lower-resolution source. For icons and other non-photographic artwork, prefer SVG.
Migration checklist
To complete the dp migration, work through the following steps:- Upgrade the app to RN 0.83 and remove any RN 0.72 dp experiment flags that duplicate the new default behavior.
- Inventory numeric length values, fixed canvas constants such as
1920and1080, and any coordinate conversion helpers in your app. - Convert values tuned as physical pixels with
logicalValue = legacyPixelValue ÷ baselineScaleFactor, and leave values from a density-independent UX specification unchanged. - Treat pointer, gesture, scroll, resize, and window coordinates reported by RN 0.83 as dp.
- Change custom React-Native-to-native geometry contracts to dp, and keep pixel conversion only at documented pixel APIs.
- Replace fixed screen dimensions with Flexbox, percentages,
Dimensions, oruseWindowDimensions(). - Add local raster density variants and confirm each image has enough physical pixels for its rendered logical size.
- Test the main window, modals, pop-ups, alerts, child windows, scrolling, gestures, focus, accessibility, localization, and right-to-left layouts at each supported density.
Related topics
- Step 4: Code Migration
- Migrate Apps to React Native 0.83
- PixelRatio
- useWindowDimensions
- Measuring the Layout
- Troubleshoot React Native 0.83 Migration Issues

