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!
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.
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:
🐥 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.
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
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:
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.
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.
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.
Oof. Not quite what we were wanting, right? 🌵
Now that we have all of our elements, they look a little sad. Let’s fix that.
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!
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,
},
That looks a lot more like a button!
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 container
s 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,
},
✨MAGIC!✨
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.
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
.
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'
.
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. 🤓
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!