Building a Landing Page in React Native Using Flexbox

Holly White

Styling a React Native app can be quite painful if you aren’t familiar with its styling powerhouse: the Flexbox layout module. While we can style with JavaScript, understanding and implementing Flexbox layout is an absolute essential for UI development with React Native. In this walkthrough, we’re going to build a landing page using Flexbox.

Spoiler alert, we won't implement Flexbox until the end!

About Flexbox

You’re probably already familiar with flexbox layout with CSS, and React Native’s implementation of Flexbox is almost the same. Flexbox is a powerful and efficient styling tool optimized for building user interfaces, especially for mobile interfaces. By using the flex property in a component’s style, we can enlarge and shrink dynamically based on the space available.

The flex property in React Native is a little bit different than with CSS, and instead works a little more like the fr unit in CSS, where the number value provided represents a proportion of the space taken. So in React Native flex expects just a simple number value.

Aside from the flex property being different than with the CSS flex shorthand property, the other difference between React Native’s implementation of flexbox and the CSS implementation is that the flex-direction defaults to a value of column in React Native.

Let’s Do It

In our example project we’re going to build a landing page for AlligatorChef 🐊, the number one fictional source for cajun bacon recipes since 1987.

Here's how our project should look when we're finished:

AlligatorChef 🐊 Voilà!

🐥 If you’re new to React Native, our tutorial Getting Started with React Native and Expo is a stellar way to prepare for this tutorial.

🚀 React Native Quickstart

In your terminal run the following commands to create a new React Native project, change into the new directory, initiate the project and then enter i for iOS.

$ create-react-native-app AlligatorChef
$ cd AlligatorChef
$ npm start
$ i

What Do We Have Here?

We can already see an example of Flexbox being used in the initial code obtained with Create React Native App with the use of the flex poperty in the call to StyleSheet.create. Take a look at the App.js file. Seems like they might be giving us a hint that Flexbox is key to styling in React Native:

App.js

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

This is telling us that the container should stretch to fit the entire screen.

Next steps

Now that we have our default project, let’s make a few modifications.

Let’s first add two Text elements for our headers.

Replace:

<Text>Open up App.js to start working on your app!</Text>
<Text>Changes you make will automatically reload.</Text>
<Text>Shake your phone to open the developer menu.</Text>

With:

<Text style={styles.h1}>AlligatorChef</Text>
<Text style={styles.h2}>Providing cajun bacon recipes since 1987.</Text>

Not much to look at, right? Let’s add some styles in the StyleSheet to spice it up. In one big swoop, replace everything you have with the following styles, including the default container. Your StyleSheet should now look exactly like this:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'space-between',
    backgroundColor: '#000',
    alignItems: 'center',
    width: '100%',
  },
  h1: {
    color: '#008F68',
    fontSize: 40,
  },
  h2: {
    color: '#FAE042',
    fontSize: 18,
    marginTop: 8,
  },
});

Let’s talk a little bit about what we just changed. You probably noticed the colors and fonts, but there’s one sparkling example that will explain why your app is looking a little spacey.

We changed justifyContent from center to space-between. If we change it back to center, everything will look happy and centered again, but we have much more to add. When using justifyContent: 'space-between' we’re getting each item spaced evenly between the top and the bottom of the screen. This is why our h1 is glued to the top and h2 to the bottom.

Images and Buttons

Rather than remedy this immediately, we’d prefer to create a little more chaos. Let’s go ahead and add an Image and a Button.

Replace your current code with the code below, while keeping the styles declaration:

import React from 'react';
import { StyleSheet, Text, View, Button, Image } from 'react-native';
import Logo from './assets/chef.png';

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.h1}>AlligatorChef</Text>
        <Text style={styles.h2}>Providing cajun bacon recipes since 1987.</Text>
        <Image
          source={Logo}
          style={styles.image}
        />
        <Button
          title="LET'S START"
          style={styles.button}
          onPress={() => this.onPress()}
          color="#fff"
        />
      </View>
    );
  }
}

// ...

Next, in the root folder, create a folder called assets. Generally we like to keep images in an assets folder to be easily accessible to all components in our project. Add the image file you’d like to use as your AlligatorChef 🐊 logo to this folder.

React Native is a bit fickle with images and might give you some issues. For this use case, make sure you’re using a png image.

Without Flexbox

Oof. Not quite what we were wanting, right? 🌵

Styling

Now that we have all of our elements, they look a little sad. Let’s fix that.

Images in React Native need a size

As a best practice in React Native, we always need to give our images a size. If you’re ever having an issue with an image not showing up, ensure that you’re assigning it a size. As you can see, we already gave the image a class in its style prop so let’s give that class some attributes. In your StyleSheet add the lines below to tame that big ole’ gator.

image: {
  width: 300,
  height: 260,
  justifyContent: 'center',
},

He looks much more manageable now!

My button doesn’t look like a button!

React Native buttons are quite picky as well. Rather than having an opening and closing <Button> with text between, React Native requires a title prop. If you look at the supplied code above, you’ll notice we included that to avoid some errors.

React Native requires us to send-in props to the Button, but it also requires us to create a style for the View that contains the button. Let’s go ahead and add a container and a class to our StyleSheet.

First add a View with the class of buttonContainer to your code:

<View style={styles.buttonContainer}>
  <Button
    title="LET'S START"
    style={styles.button}
    onPress={() => this.onPress()}
    color="#fff"
  />
</View>

Next, add the following to your stylesheet:

buttonContainer: {
  backgroundColor: '#008F68',
  borderRadius: 5,
  padding: 8,
  margin: 8,
},

Button styling

That looks a lot more like a button!

Are You Ready for Some Flexbox?!

Okay, let’s get the rest of this page under control by using the magical Flexbox. Ya’ll ready for this? 🏀

We’re going to start by adding three containers within our original container. If you replace your initial code with the following, you’ll notice a few new classes, topContainer, middleContainer, and bottomContainer.

import React from "react";
import {
  StyleSheet,
  Text,
  View,
  Button,
  Image,
  ProgressViewIOS
} from "react-native";
import Logo from "./assets/chef.png";

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.topContainer}>
          <Text style={styles.h1}>AlligatorChef</Text>
          <Text style={styles.h2}>
            Providing cajun bacon recipes since 1987.
          </Text>
        </View>
        <View style={styles.middleContainer}>
          <Image source={Logo} style={styles.image} />
        </View>
        <ProgressViewIOS number={1} />
        <View style={styles.bottomContainer}>
          <View style={styles.buttonContainer}>
            <Button
              title="LET'S START"
              style={styles.button}
              onPress={() => this.onPress()}
              color="#fff"
            />
          </View>
        </View>
      </View>
    );
  }
}

Let’s add these classes to our current StyleSheet to see some magic.

topContainer: {
  flex: 2,
  justifyContent: 'center',
  alignItems: 'center',
},
middleContainer: {
  flex: 3,
  justifyContent: 'flex-start',
  alignItems: 'center',
},
bottomContainer: {
  justifyContent: 'flex-end',
  width: '90%',
  margin: 20,
  padding: 10,
},

Alligator Chef 🐊

✨MAGIC!✨

Let’s discuss how Flexbox saved the day

We assigned flex: 2 to topContainer, giving it a flex-grow value of 2, so that it takes 2/5ths of the original container. We also told it to align and justify everything in the center. Take a look at the screenshot below for a visual demo.

2/5ths Example

We assigned flex: 3 to middleContainer to take the remaining 3/5ths of the original container. Rather than using justifyContent: 'center', we instead used justifyContent: 'flex-start'. This is why our AlligatorChef 🐊 image is aligned to the top of middleContainer.

3/5ths Example

Lastly since we aren’t concerned with how much of the page the Button takes up, we do not need to specify a flexBasis. We only need the button to be at the bottom of the page, so we assign bottomContainer justifyContent: 'flex-end'.

That’s it 🐿

Though this is just a general introduction, the Flexbox layout module has a ton to offer for not only React Native but general web development.

👉 Always remember to look for easter eggs. 🤓

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#