Learn React Native

Styling in React Native

Mobile apps are not just built with text alone. There are a lot more components used such as images, buttons etc. In addition, properly arranging and styling the components is also important. In this chapter, we will look into two more core components, Image and SafeAreaView. Let's see how we can make our user interface better with styles.

What is SafeArea?

SafeArea is the portion of the screen where we can display content that won't be hidden by device notch or home indicator. If you run the Hello, React Native! example from the previous chapter on an iPhone a portion of that text will be hidden under the notch.

Hello, React Native!

To avoid this situation we should display content in the safe area of the screen. In the below screenshots the areas highlighted in red is the unsafe area.

SafeArea iOS

We can wrap any component inside the SafeAreaView and that will push the content away from the unsafe area. Let's see how we can add SafeAreaView to the Hello, React Native! example.

1import React from "react";
2import { View, Text, SafeAreaView } from "react-native";
3
4const App = () => {
5  return (
6    <SafeAreaView>
7      <View>
8        <Text>Hello, React Native!</Text>
9      </View>
10    </SafeAreaView>
11  );
12};
13
14export default App;

Hello, React Native!

See how wrapping the root View component inside the SafeAreaView pushed the content to the safe area and made it properly visible.

SafeAreaView will only work on iOS devices with version 11 or above.

Style

Now that we know how to put things on the screen properly, let's learn how we can add some style. In React Native we can add styles to any core component using the style property(prop). There are multiple ways we can provide value to the style prop. We will start with the simple method, passing the style object directly to the style prop.

1const App = () => {
2  return (
3    <SafeAreaView>
4      <View>
5        <Text
6          style={{
7            color: "blue",
8            fontSize: 32,
9          }}
10        >
11          Hello, React Native!
12        </Text>
13      </View>
14    </SafeAreaView>
15  );
16};

Styled Hello, React Native!

In the above code snippet, we are giving the text a blue color and font size of 32. React Native use React and it use JSX for layout. In JSX you can pass a constant value to props directly or pass javascript expression inside curly brackets. In the above snippet, we are passing a JavaScript object to style prop.

Style attributes

React Native mostly use CSS attributes with camelCase instead of kebab-case for styling. In the above example, we are using the fontSize and color attributes to set font size and text color respectively. React Native doesn't support all the style attributes available in CSS and every core component won't support all available attributes. We are not expecting you to have CSS experience, we will learn more and more attributes as we progress through this book.

Let's add two more style attributes to the Text component.

1backgroundColor: '#ffefd5',
2textAlign: 'center',

This will add a background color to the text and align it in the center.

Styled Hello, React Native!

Color Values

In React Native you can specify color in multiple ways.

  • Predefined color values: e.g. red, gold, coral.

  • Hexadecimal: #f0f(#rgb), #ff00ff(#rrggbb), f0ff(#rgba), #ff00ff00(rrggbbaa).

  • RGB: rgb(255, 0, 255) and `rbga(255, 0, 255, 1).

    Here the r, g, b and a stands for red, green, blue and alpha respectively. Check out the official doc to know more about colors.

Text Styles

Text component can be styled using a lot more attributes. Check out the official doc for all available options.

Reusing Styles

Inline-styles are easy to create, but it has two major drawbacks. First of all, it will clutter our component code pretty easily and thus affects the code readability. The second problem with inline styles is that we can't reuse the styles. Let's jump into an example where we have the scope for reusing styles.

Styled Hello, React Native!

In this screen, we have two text elements with the exact same style except for the color. On using inline style the code will look like this.

1const App = () => {
2  return (
3    <SafeAreaView>
4      <View>
5        <Text
6          style={{
7            color: "blue",
8            fontSize: 24,
9            textAlign: "center",
10            marginHorizontal: 16,
11            marginTop: 12,
12          }}
13        >
14          MONEY Master the Game: 7 Simple Steps to Financial Freedom
15        </Text>
16        <Text
17          style={{
18            color: "grey",
19            fontSize: 24,
20            textAlign: "center",
21            marginHorizontal: 16,
22            marginTop: 12,
23          }}
24        >
25          by Anthony Robbins
26        </Text>
27      </View>
28    </SafeAreaView>
29  );
30};

Here, we have a possibility for code reuse but the same cannot be done with inline styles.

Since style prop accepts object we can extract the styles to object.

1const styles = {
2  text: {
3    fontSize: 24,
4    textAlign: "center",
5    marginHorizontal: 16,
6    marginTop: 12,
7  },
8  blueText: {
9    color: "blue",
10  },
11  greyText: {
12    color: "grey",
13  },
14};

Here we have created a styles object. Now we have to pass styles.text to both Text components and styles.blueText to the first one and styles.greyText to the second. Since style props accept an object we can use the spread operator to combine multiple objects to one.

1<SafeAreaView>
2  <View>
3    <Text style={{ ...style.text, ...style.blueText }}>
4      MONEY Master the Game: 7 Simple Steps to Financial Freedom
5    </Text>
6    <Text style={{ ...style.text, ...style.greyText }}>by Anthony Robbins</Text>
7  </View>
8</SafeAreaView>

This is also a little messy, and there is a better way to do it. Style prop also accepts array of objects.

Instead of this.

1style={{...style.text, ...style.blueText}}

We can change it to this.

1style={[style.text, style.blueText]}

StyleSheet

Even though we can use plain JavaScript objects for style it is not a good practice. What we can do instead is to use the inbuilt StyleSheet API. The StyleSheet API has a lot of advantages over the normal object, like compile-time checks, performance improvements and better code auto-completion to name a few. Let's re-write the entire App component to use the StyleSheet.create API.

1import React from "react";
2import { View, Text, SafeAreaView, StyleSheet } from "react-native";
3
4const styles = StyleSheet.create({
5  text: {
6    fontSize: 24,
7    textAlign: "center",
8    marginHorizontal: 16,
9    marginTop: 12,
10  },
11  blueText: {
12    color: "blue",
13  },
14  greyText: {
15    color: "grey",
16  },
17});
18
19const App = () => {
20  return (
21    <SafeAreaView>
22      <View>
23        <Text style={[styles.text, styles.blueText]}>
24          MONEY Master the Game: 7 Simple Steps to Financial Freedom
25        </Text>
26        <Text style={[styles.text, styles.greyText]}>by Anthony Robbins</Text>
27      </View>
28    </SafeAreaView>
29  );
30};
31
32export default App;

Layout

Till now whatever we have put into the screen is displayed in a single column. This is because React Native use the Flexbox algorithm to layout components and the default direction is column. It is the same Flexbox algorithm from CSS with few limitations. Let's modify the App component to display both the text component in a single row.

1const styles = StyleSheet.create({
2  container: {
3    flexDirection: "row", // Change flex direction to row
4  },
5  text: {
6    flex: 1, // Set flex value to 1 for both Text component
7    fontSize: 24,
8    textAlign: "center",
9    marginHorizontal: 16,
10    marginTop: 12,
11  },
12  blueText: {
13    color: "blue",
14  },
15  greyText: {
16    color: "grey",
17  },
18});
19
20const App = () => {
21  return (
22    <SafeAreaView>
23      <View style={styles.container}>
24        <Text style={[styles.text, styles.blueText]}>
25          MONEY Master the Game: 7 Simple Steps to Financial Freedom
26        </Text>
27        <Text style={[styles.text, styles.greyText]}>by Anthony Robbins</Text>
28      </View>
29    </SafeAreaView>
30  );
31};

Styled Hello, React Native!

Flex Direction

The flexDirection attribute decides the flow of elements in a flex container. The default value for flexDirection is column and here we are changing it to row.

Flex

The flex attribute will define how much space the child component will occupy in the container along the flex-direction. In our example, we are using flex value 1 for both child components. This will divide the container into 2 and will give 1 portion to each element.

We can do a lot more with Flexbox, for now, we will stop here and will learn more in upcoming chapters.

Image Component

We already know how to display text on the screen. Let's add one more thing to our toolkit, images.

Image is the React Native core component we can use to display images from the network(using URL), project files and device storage. Let's add an image to the App component.

1import React from "react";
2import { View, Text, SafeAreaView, StyleSheet, Image } from "react-native";
3
4const styles = StyleSheet.create({
5  text: {
6    fontSize: 24,
7    textAlign: "center",
8    marginHorizontal: 16,
9    marginTop: 12,
10  },
11  blueText: {
12    color: "blue",
13  },
14  greyText: {
15    color: "grey",
16  },
17  image: {
18    width: 200,
19    height: 300,
20  },
21});
22
23const App = () => {
24  return (
25    <SafeAreaView>
26      <View>
27        <Image
28          style={styles.image}
29          source={{
30            uri:
31              "https://user-images.githubusercontent.com/19279756/109667147-da6f4180-7b95-11eb-9d8f-cca772d8733a.jpg",
32          }}
33        />
34        <Text style={[styles.text, styles.blueText]}>
35          MONEY Master the Game: 7 Simple Steps to Financial Freedom
36        </Text>
37        <Text style={[styles.text, styles.greyText]}>by Anthony Robbins</Text>
38      </View>
39    </SafeAreaView>
40  );
41};
42
43export default App;

Styled Hello, React Native!

The Image component accept a source prop where we can directly require and pass a local image file or an object with the uri pointing to the image path in device storage or on the internet.

Later in this book we will explore the Image component in more detail.

Assignment

Now that we have learned styling try to make our existing opus app more beautiful as shown in the below image.

React Native task 01