Tutorial

How To Use Styling in React Native Apps

React

Introduction

When working with React Native, by default it does not use HTML and CSS as a web application.

In fact, right out of the box, everything is automatically styled based on Flexbox.

In this article, you will be introduced to how to apply styling to React Native applications.

Prerequisites

If you would like to follow along with this article, you will need:

  • Familiarity with using CSS properties and values.
  • Familiarity with using JSX syntax in React Native.

Using StyleSheet

The first thing to know about React Native styling is to use the StyleSheet component.

First, import it like this:

import { StyleSheet } from 'react-native';

After that, you can use it like this:

const styles = StyleSheet.create({
  container: {
    height: 100
  }
})

Then, add it to style your component appropriately, like this:

<View style={styles.container}></View>

You could also go the inline route, like the following:

<View style={{height: 100}}></View>

This code would produce the same result.

Handling Pixels

You may have noticed we did not indicate any unit to the 100 in height: 100. You may be used to writing px, vm, etc. And the question is, what units are used by default in React Native?

That is a pretty complex question, which has taken more than one article to answer. For iOS, they are “logical points”, and Android uses DIP. There is a lot of reasoning behind this, as well as the logic as to why this was chosen. There are many different screen sizes and different resolutions on the same screen size. So if we used normal pixels it would look pixelated on some phones; but the idea behind “points” is to make things look relatively the same on a pixel-dense, high-resolution screen, as it does on a low-resolution screen.

Though it isn’t perfect, it will look roughly the same from one platform to the other. There is a calculation that goes on behind the scenes to determine what your height, width, borderWidth, etc, would look like on the screen.

You can also use 'auto' or percentages, but you wrap it in quotes, like this:

<View style={{ height: '100%' }}></View>

This code will produce a full height View.

Wrapping the Entire Screen

Now, one thing to know about setting a <View> to fill the entire screen, is a phone like the iPhone X has part of the screen covered with the user interface (UI). Normally, part of your screen in which you place your elements will be hidden under the covered part of the screen.

For this, use the React Native component <SafeAreaView> to wrap the rest of your components and you can be sure you will see all of your screen.

Alternatively, you can use flex: 1.

React Native uses Flexbox by default so you don’t need to worry about applying display: flex. And unlike in the web version which has flexDirection set to row by default, React Native uses a flexDirection set to column. Setting the style to flex: 1 will apply flex-grow to the component to occupy the entire main axis of the Flexbox container.

Both approaches will ensure that the content remains visible.

Adding Margin and Padding

On the web, you can use margin and padding shorthand.

However, React Native has additional styling helpers for applying margin and padding.

For instance, to give an element a top and bottom margin of 20 you could set in like this:

<View style={{marginVertical: 20}}></View>

You could also give it padding of top and bottom:

<View style={{paddingVertical: 20}}></View>

In addition to helpers for “Vertical”, there are also helpers for “Horizontal”: paddingHorizontal and marginHorizontal.

There is also “Start” and “End” you can tag on the end of margin and padding. Whenever you see “Start” and “End” in styles, you can know these depend on the flexDirection of the container

If the flexDirection is row then marginStart behaves like marginLeft.

If the flexDirection is row-reverse then marginStart behaves like marginRight.

Also, keep in mind, “start” and “end” override marginLeft and marginRight, paddingLeft and paddingRight.

Adding Shadows and Borders

The normal border style in CSS is not available in React Native styles. You have to break it down into borderColor and borderWidth. With those two indicated, you have enough for a border. Also, you can pick which side receives which color and width.

There’s also borderRadius, as you may be used to, that gives a radius to each corner. You can pick each individual radius with top-start, top-end, bottom-start, or bottom-end, like this: borderTopStartRadius: 20, or you can use the easier top-left, top-right, and so on.

Finally, you can use borderStyle to pick from dashed, dotted, or solid borders.

As for shadows in React Native, you won’t be using the box-shadow you might be familiar with.

Instead, React Native has styles that only work in iOS:

shadowOffset: { height: 3, width: 3 }, 
shadowColor: '#000000',
shadowOpacity: 0.5,
shadowRadius: 5

In older versions of Android, there isn’t a great, built-in solution with React Native. You can set the elevation property, but this isn’t customizable and won’t work well with other styles - such as border and background-color.

Handling Differences Between Platforms

In the last section, we saw the first major difference between platforms: one has shadow styles, but the other doesn’t. Now the good thing is, in the example above, Android will simply ignore the styles it doesn’t support. It won’t work, but at least you won’t receive any errors. That’s true for the most part with all styles you’ll find that isn’t supported by a platform - it will be ignored.

However, you’ll find quite a lot of difference in appearance from one platform to the other, even with perfect, clean styles.

To keep the styling similar across platforms, let’s import the Platform component from React Native.

import { View, StyleSheet, Platform } from 'react-native';

{/* ... */}
<View style={styles.container}></View>
{/* ... */}

const styles = StyleSheet.create({
  container: {
    height: Platform.OS === 'android' ? 100 : 20,
    backgroundColor: Platform.OS === 'ios' ? 'yellow' : 'blue',
    ...Platform.select({ ios: { width: 100 } })
  }
})

Notice the two different ways here to set platform-specific styles. One way comes after the style prop, using a ternary operator:

height: Platform.OS === 'ios' ? 100, 20

This works well in most situations, but what if you don’t even want to set a style in one platform? That’s where ...Platform.select() comes in. This allows you to specify a style on one platform only, or both:

...Platform.select({ ios { width: 100 }, android: { width: 75 } })

This code will define a width of 100 for iOS platforms and a width of 75 for Android platforms.

Conclusion

In this article, you were introduced to how to apply styling to React Native applications.

You’ll notice in React Native that styles are different from component to component, unlike the web where basically every element can use every style.

In the official React Native docs for the style prop for the Text component. It does not possess the full breadth of the properties available on the web. And some components, like Button, don’t even have a style prop.

You can also use components like <TouchableOpacity> and of course, <View>, which have most of the styling props available. Alternatively, you could also import the styled-components library and use normal CSS.

Creative Commons License