What about responsive UI ?
Responsive UI is important! No UI developer can deny that, while most of us have struggled at some point to deliver one. As a React Native developer now, you have to deliver the same or very similar result for many mobile and tablet screens of different sizes, analysis, scale factor, pixel density etc.
When I started coding with RN I remember thinking:
There has to be an internal mechanism of the framework to address responsiveness — if not, worst case scenario I will use percentages everywhere…
Both of these hypothesis though were wrong… And I discovered it the hard way when I started developing my first UI.
Percentage CSS value is NOT fully supported
Although this has improved a lot from 1+ year ago, it still is the case. There are CSS properties that do not support percentage values in RN, although they do in “normal” Web Development. To mention a few: margin, border-width and border-radius. And if someone tries to set a percentage value, RN will either ignore it completely or the application will crash.
Improvements are being made and support is added as time passes. To wait for the framework to catch up though is prohibitive for the people that already work with React Native in production apps. Stay with me to take a deeper look at a few RN mechanisms, how our team figured out a solution and a real example of our work.
React Native and independent pixels
When coding a CSS value in “pixels” in React Native, it’s actually independent pixels (dp or dpi) and not screen pixels. It’s a different unit of measurement (probably inspired by it’s use in Android development) that RN uses internally.
Let’s take a look at the following code (we use styled components package and syntax instead of accessing directly the RN StyleSheet component):
const HeaderText = styled.Text`
padding-top: 20;
font-size: 15;
font-family: Kano;
width: 100%;
text-align: center;
`;
You can see that both properties padding-top
and font-size
are written as plain numbers and there is no px
suffix next to them. To find the actual screen pixels we can use the following equation:
px = dp * scaleFactor
For more info you can have a look at Android’s guide for pixel densities here, Android’s screen compatibility overview and paintcodeapp’s guide for iPhone resolutions.
Someone might think here that we can use independent pixels everywhere and get the responsive UI we are looking for. Unfortunately that is not the case because scaleFactor
depends on pixel density. That being said, we could develop an app with independent pixels only if all of the devices that the app would run on share the same pixel density (ppi) over their screens. In reality though, each manufacturer creates his own pixel density screens.
Let’s come up with a mechanism for responsive UI
The idea is simple. Since percentage will not always work, let’s provide the “correct” dp value for every different screen dynamically. Let’s see an example of how to do that. Below we can see the Profile scene from Math Warriors Android game. Let’s focus at the 4 big blue tiles at the bottom half:

What we want to achieve here for our design to be responsive, is the tiles to take over 98% of the screen’s width in dp and 10% of the screen’s height in dp. And that should be the case for every single screen. That translates to:
Let’s identify the screen’s dimensions (width, height) in dp and then multiply it with a factor — in our case 98% and 10% for width and height respectively. For flexibility in our code we create the 2 functions below:
import {Dimensions, PixelRatio} from 'react-native';const widthPercentageToDP = widthPercent => {
const screenWidth = Dimensions.get('window').width;
// Convert string input to decimal number
const elemWidth = parseFloat(widthPercent); return PixelRatio.roundToNearestPixel(screenWidth * elemWidth / 100);
};const heightPercentageToDP = heightPercent => {
const screenHeight = Dimensions.get('window').height;
// Convert string input to decimal number
const elemHeight = parseFloat(heightPercent);return PixelRatio.roundToNearestPixel(screenHeight * elemHeight / 100);
};export {
widthPercentageToDP,
heightPercentageToDP
};
And now inside our Profile view we simply call the functions by providing the desired percentage amount (for width or height) as an argument. For the example above we have the following code (again the awkward syntax is because of styled components use):
const Tile = styled.View`
width: ${widthPercentageToDP('98%')};
height: ${heightPercentageToDP('10%')};
.
.
.
`;
That way we can generate a dynamic result that adopts to all different screen sizes!
Let’s test our example!
In order to verify our UI development we have a set of Android, iOS emulators that we use to check the results. Let’s see how our code has been transformed to UI:
Smartphones






Tablets



What do you think?
What do you think about this solution? Feel free to offer your perspective and ideas to the comments section below.