Emmanuel Etukudo I am a full-stack developer with more than five years of experience, with a preference for JavaScript, Node.js, Go, React, Redux, and MongoDB.

React Native styling tutorial with examples

8 min read 2291

React Native Styling Tutorial Examples

As the demand for cross-platform mobile applications grows, so does the need for developers to adopt one codebase to build cross-platform apps that run on multiple operating systems.

There are numerous benefits to building a mobile application for multiple operating systems from one codebase. Whether you want to add support for new platform users or you’re looking to reduce your production cost, building mobile apps that operate on multiple devices is a smart strategy.

In this tutorial, we’ll show you how to style components in React Native. We’ll demonstrate how styling in React Native works by building an example e-commerce mobile application.

Here’s what we’ll cover:

To follow along with this React Native styling tutorial, you should have:

  • Familiarity with CSS, HTML, Javascript (ES6)
  • Node.js and Watchman installed on your development machine
  • iOS Simulator or Android Emulator for testing
  • A code editor installed in your development machine (e.g., VS Code)
  • A basic understanding of React

What is React Native?

React Native is an open-source mobile application framework. Launched by Facebook in 2015, mobile developers around the world use React Native to build apps for Android and iOS, as well as the web and macOS/Windows formats.

The selling point of React Native is that it enables developers to use React’s framework along with native platform capabilities.

React Native styling example

For this React Native styling demo, we’re going to build an e-commerce mobile application that displays an array of products for users to make orders based on their preferences. In particular, we’ll walk through building a landing page and cart functionality to highlight some key React Native styling concepts.

The finished application will look like this:

Ecommerce Mobile App Finished Display

We made a custom demo for .
No really. Click here to check it out.

There are two major methods approved by the React Native team to set up a new react-native project: Expo-CLI and React-native-CLI. This project is set up using react-native-cli-starter. You can read more about environment setup for both iOS and Android in the React Native docs.

How styling in React Native works

Styling in React Native is done using JavaScript. Since React components have support for the style prop, you can also create an object of style values and pass them on to the component as props. The style names work exactly the same way as in CSS, except they’re written in camel-case (e.g., backgroundColor).

import React from "react";
import {View, Text} from "react-native";

const Home = () => {
    return (
        <View style = {{flex: 1, backgroundColor: "#ffffff" }}>
          <View>
            <Text style={{fontSize: 12, color: "#000" }}>Log Rocket Store</Text>
          </View>
        </View>
    )
}

How you style a React Native application depends on the complexity of your application. As it grows more complex, you can use the StyleSheet.create to define multiple styles for your application. See the example below:

import React from "react";
import {StyleSheet, View, Text} from "react-native";

const Home = () => {
    return (
        <View style = {style.container}>
          <View>
            <Text style={style.title}>Log Rocket Store</Text>
          </View>
        </View>
    )
}

const style = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: "#ffffff",
    },
    title: {
      fontSize: 12,
      color: "#000",
   }
})

The more complex your application, the more you should break down your styles into smaller pieces of reusable codes. For complex applications, I recommend you create a theme with your desired font sizes, padding, margin, and images to achieve a more modular code structure.

Building and styling a React Native app

The e-commerce mobile application has two main functionalities built with two components: the Home component and the cart-modal. To follow along, clone the starter repo here:

git clone https://github.com/emmanueletukudo/logrocket-online-store-starter.git

Navigate to the newly created log-rocket-online-store-starter directory and run npm install in your terminal/command prompt. Once installation is complete, run the command below to start metro-bundler.

npx react-native start

Metro is a JavaScript bundler built by Facebook. You may wish to read metro-bundler documentation here. If everything is set up correctly, you should have a new terminal window open similar to the screenshot below:

Metro Facebook JavaScript Bundler New Terminal Window

Now that we have our project set up and Metro bundler running, let’s run a build for our starter project.

iOS and Android

To run a build for ios, copy and paste the code below in your terminal:

npx react-native run-ios

To run a build for andriod, run npx react-native run-android in your command prompt.

You should see something like this:

Build Android Command Prompt Display

Folder structure

The folder structure for our React Native styling example is as follows.

  • assets contains all the application’s assets, including fonts, images, and icons
  • constants contains icons.js, images.js, theme.js, and index.js. All assets are stored in JavaScript constants
  • screens contains Home.js and index.js

In this tutorial, we’ll focus on styling the application and understanding when to use themes and when to use inline styling. You can explore the codebase to learn more about how everything works under the hood.

Styling React Native components

The Home component has two sections: the featured product and recent searches.

Navigate to the screens directory, replace the code in the Home component with the code below to create the Home component:

import React from "react";
import {StyleSheet, View, Text, FlatList, TouchableOpacity, Image,} from "react-native";
import { images, COLORS, SIZES, FONTS } from "../constants";
const Home = () => {
    const [selectedItem, setSelectedItem] =  React.useState(null);
    const [selectedSize, setSelectedSize] = React.useState("");
    const [featured, setFeatured] =  React.useState([
        {
            id: 0,
            name: "Jacket 4",
            img: images.jacket4,
            bgColor: "#D09040",
            price: "$250",
            type: "Featured",
            sizes: [6, 7, 8, 9, 10, 16],
        },
        {
            id: 1,
            name: "Jacket 1",
            img: images.jacket1,
            bgColor: "#D3D1C8",
            type: "Featured",
            price: "$150" ,
            sizes: [6, 7, 8, 9, 10, 12],
        },
        {
            id: 2,
            name: "Jacket 2",
            img: images.jacket2,
            type: "Featured",
            bgColor: "#303946",
            price: "$160" ,
            sizes: [6, 7, 8, 9, 10],
        }
    ])
    const [recentSearches, setRecentSearch] = React.useState([
        {
            id: 0,
            name: "Jacket 4",
            img: images.jacket4,
            bgColor: "#D09040",
            price: "$250",
            type: "Featured",
            sizes: [6, 7, 8, 9, 10, 16],
        },
        {
            id: 1,
            name: "Sweater 3",
            img: images.sweater3,
            type: "Featured",
            bgColor: "#0F5144",
            price: "$100" ,
            sizes: [6, 7, 8, 9, 10, 16, 18],
        },
        {
            id: 2,
            name: "Sweater 5",
            img: images.sweater5,
            type: "Featured",
            bgColor: "#888983",
            price: "$100" ,
            sizes: [6, 7, 8, 9, 10, 18],
        },
        {
            id: 7,
            name: "Jacket 1",
            img: images.jacket1,
            bgColor: "#D3D1C8",
            type: "Featured",
            price: "$150" ,
            sizes: [6, 7, 8, 9, 10, 12],
        },
        {
            id: 8,
            name: "Jacket 2",
            img: images.jacket2,
            type: "Featured",
            bgColor: "#303946",
            price: "$160" ,
            sizes: [6, 7, 8, 9, 10],
        },
        {
            id: 3,
            name: "Hat 1",
            img: images.hat1,
            type: "Featured",
            bgColor: "#26232A",
            price: "$100" ,
            sizes: [6, 7, 8, 9, 10, 16],
        },
        {
            id: 4,
            name: "Shirt 1",
            img: images.shirt1,
            type: "Featured",
            bgColor: "#575569",
            price: "$100" ,
            sizes: [6, 7, 8, 9, 10, 16],
        },
        {
            id: 5,
            name: "Shirt 2",
            img: images.shirt2,
            type: "Featured",
            bgColor: "#2B3A6B",
            price: "$100" ,
            sizes: [6, 7, 8, 9, 10, 16],
        },
        {
            id: 6,
            name: "Shoe 1",
            img: images.shoe1,
            type: "Featured",
            bgColor: "#9E7348",
            price: "$100" ,
            sizes: [6, 7, 8, 9, 10, 12],
        },

    ])
    function renderFeaturedItems(item, index){
        return(
            <TouchableOpacity 
            style={{height: 300, width: 200, justifyContent: "center", marginHorizontal: SIZES.base }}
            onPress={() => {
                setSelectedItem(item);
                setShowAddToCartModal(true);
            }}
            >
                <Text style={{color: COLORS.lightGray, ...FONTS.h5}}>{item.type}</Text>
                <View style={[{
                    flex: 1,
                    justifyContent: "flex-end",
                    marginTop: SIZES.base,
                    borderRadius: 10,
                    marginRight: SIZES.padding,
                    backgroundColor: item.bgColor,
                    paddingRight: SIZES.padding,
                    paddingBottom: SIZES.radius,
                }, style.featuredShadow ]}>
                    <View style={style.featuredDetails}>
                        <Text style={{color: COLORS.white, ...FONTS.body4, marginTop: 15}}>{item.name}</Text>
                        <Text style={{color: COLORS.white, ...FONTS.h2}}>{item.price}</Text>
                    </View>
                </View>
                <Image 
                source={item.img} 
                resizeMode="cover"
                style = {{
                    position: "absolute",
                    top: 25,
                    right: 20,
                    width: "90%",
                    height: 200,
                }}
                />
            </TouchableOpacity>
        )
    }
// paste recent searches code

// paste renderSizes 
    return(
       <View style={style.container}>
            <Text style={{marginTop: SIZES.radius, marginHorizontal: SIZES.padding, ...FONTS.h2}}>FEATURED</Text>
            {/* Featured */}
            <View style={{height: 260, marginTop: SIZES.radius}}>
                <FlatList 
                horizontal
                showsHorizontalScrollIndicator={false}
                data={featured}
                keyExtractor={item => item.id.toString()}
                renderItem ={({item, index}) => renderFeaturedItems(item, index)}
                />
            </View>
          {/* Recent Searches */}

          {/* Modal */}

        </View>
    )
}
const style = StyleSheet.create({
    container:{
        flex: 1,
        backgroundColor: COLORS.white,
    },
    eaturedShadow: {
        shadowColor: "#000",
        shadowOffset:{
            width: 0,
            height: 5,
        },
        shadowOpacity: 0.29,
        shadowRadius: 4.65,
        elevation: 7
    },
    featuredDetails: {
        position: "absolute",
        top: 160,
        left: 30,
        flexDirection: "column",
        marginLeft: 25,
        marginBottom: 8,
    },
})

export default Home

If you run npx react-native run-ios, your app should now look like the screenshot below:

Run Ios React Native App Visual Example

Breaking down the code

Let’s take a closer look at the code.

The majority of the font sizes, padding, and margins used above are declared in the theme.js file located in the constant folder. Within the renderFeaturedItems function, you notice I combined inline styling and prop approach to style the featured items. The react-native style prop accepts an array, so you can pass a second argument to the style.

See the example below:

<View style={[{
                    flex: 1,
                    justifyContent: "flex-end",
                    marginTop: SIZES.base,
                    borderRadius: 10,
                    marginRight: SIZES.padding,
                    backgroundColor: item.bgColor,
                    paddingRight: SIZES.padding,
                    paddingBottom: SIZES.radius,
                }, style.featuredShadow ]}>

In the code block above, the style prop value is wrapped in a bracket [], meaning the prop will accept an array of objects as values. The second argument of the style prop is created using Stylesheet.create(). As stated earlier, this approach is popular in complex React Native applications and is a good way to support multiple styles.

Now that we’ve built the first section of the Home component, let’s build the last one: the recent searches section.

Before we begin, let’s give some thought to what the recent searches structure should look like. We need to first create a flex container with its flex direction set to row, and two columns, which will act as direct children of the container. The first column contains an image; the other is a flex container that houses the product image, product name, and price.

App Display Flex Direction Row Column

When styling in React Native, just like in CSS, you should always map your UI components to CSS properties before you begin styling your app. These will give you a broader overview of how to style your entire application from the ground up.

To build the second section of the Home component, find the // paste recent searches code comment and copy/paste the code beneath the comment.

  function renderRecentSearches(item, index){
        return(
            <TouchableOpacity
            style = {{flex: 1, flexDirection: "row"}}
            onPress= {() => {
                setSelectedItem(item);
                setShowAddToCartModal(true);
            }}
            >
            <View style={{flex: 1, alignItems: "center", justifyContent: "center"}}>
                <Image
                source = {item.img}
                resizeMode = "contain"
                style = {{
                    width: 130,
                    height: 100,
                }}
                />
            </View>
            <View style={{
                flex: 1.5,
                marginLeft: SIZES.radius,
                justifyContent: "center",
            }}>
                <Text>{item.name}</Text>
                <Text style={{...FONTS.h3}}>{item.price}</Text>
            </View>
            </TouchableOpacity>
        )
    }

Next, find the {/* Recent Searches */} comment in Home.js and paste the code below under it.

<View style={[{
                flex: 1, 
                flexDirection: "row",
                marginTop: SIZES.padding, 
                borderTopLeftRadius: 30, 
                borderTopRightRadius: 30,
                backgroundColor: COLORS.white}, 
                style.recentSearchShadow]
                }>
                <View style={{width: 70, height: "100%", marginLeft: SIZES.base}}>
                    <Image 
                    source={images.searches}
                    style={{width: "100%", height: "100%", resizeMode: "contain"}}
                    />
                </View>
                <View style={{flex: 1, paddingBottom: SIZES.padding}}>
                    <FlatList 
                    showsVerticalScrollIndicator = {false}
                    data = {recentSearches}
                    keyExtractor = {item => item.id.toString()}
                    renderItem = {({item, index}) => renderRecentSearches(item, index)}
                    />
                </View>
            </View>

Adding shadows

Add the code below to the StyleSheet.create to complete the styling of the recent searches section of the Home component.

recentSearchShadow:{
        shadowColor: "#000",
        shadowOffset:{
            width: 0,
            height: 5,
        },
        shadowOpacity: 0.29,
        shadowRadius: 4.65, 
        elevation: 7
    },
    recentSearches: {
        width: "100%",
        transform: [{ rotateY: "180deg" }]
    },

Adding shadows to a component in React Native is quite different from how it is done in CSS. You need to specify the shadowColor, ShadowOffset, ShadowOpacity, ShadowRadius and elevation.

That this only works in iOS to create a shadow. To add shadows to a component in Android, see the official instructions here.

Styling the modal

Finally, let’s create the modal to display each selected product. Find the // paste renderSizes comment in Home.js and copy/paste the following code underneath it:

function renderSizes(){
        return(
            selectedItem.sizes.map((item, index) => {
                return(
                    <TouchableOpacity
                    key = {index}
                    style={{
                        width: 35,
                        height: 25,
                        alignItems: 'center',
                        justifyContent: 'center',
                        marginHorizontal: 5,
                        marginBottom: 10,
                        backgroundColor: selectedItem.sizes[index] == selectedSize ? COLORS.white : null,
                        borderWidth: 1,
                        borderColor: COLORS.white,
                        borderRadius: 5,
                    }}
                    onPress={() => {
                        setSelectedSize(item);
                    }}
                    >
                        <Text style={{ color: selectedItem.sizes[index] == selectedSize ? COLORS.black : COLORS.white, ...FONTS.body4 }}>{item}</Text>
                    </TouchableOpacity>
                )
            })
        )
    }

Paste the following code beneath the comment {/* Modal */} in the Home component:

{ selectedItem && 
            <Modal
            animationType = "slide"
            transparent= {true}
            visible =  {showAddToCartModal}
            >
            <BlurView 
            style={style.blur}
                blurType = "light"
                blurAmount = {20}
                reducedTransparencyFallbackColor = "white"
                >
                <TouchableOpacity
                style={style.absolute}
                onPress= {() => {
                    setSelectedItem(null);
                    setSelectedSize("");
                    setShowAddToCartModal(false);
                }}
                >
                </TouchableOpacity>
                {/* Modal content */}
                <View style={{justifyContent: "center", width: "85%", backgroundColor: selectedItem.bgColor}}> 
                   <View>
                   <Image
                    source = {selectedItem.img}
                    resizeMode = "contain"
                        style = {{
                            width: "100%",
                            height: 170,
                        }} 
                    />
                   </View>
                   <Text style={{ marginTop: SIZES.padding, marginHorizontal: SIZES.padding, color: COLORS.white, ...FONTS.h2}}>{selectedItem.name}</Text>
                   <Text style={{ marginTop: SIZES.base / 2, marginHorizontal: SIZES.padding, color: COLORS.white, ...FONTS.body3 }}>{selectedItem.type}</Text>
                   <Text style={{ marginTop: SIZES.radius, marginHorizontal: SIZES.padding, color: COLORS.white, ...FONTS.h1 }}>{selectedItem.price}</Text>
                   <View style={{ flexDirection: "row", marginTop: SIZES.radius, marginHorizontal: SIZES.padding}}>
                        <View>
                        <Text style={{color: COLORS.white, ...FONTS.body3}}>Select Size</Text>
                        </View>
                        <View style={{flex: 1, flexWrap: "wrap", flexDirection: "row", marginLeft: SIZES.radius}}>
                        {renderSizes()}
                        </View>
                   </View>

                   <TouchableOpacity
                   style={{width: "100%", height: 70, justifyContent:"center", alignItems: "center", marginTop: SIZES.base, backgroundColor: 'rgba(0,0,0,0.5)'}}
                   onPress = {() => {
                    setSelectedItem(null);
                    setSelectedSize("");
                    setShowAddToCartModal(false);
                   }}
                   >
                       <Text style={{color: COLORS.white, ...FONTS.largeTitleBold}}>Add To Cart</Text>
                   </TouchableOpacity>
                </View>
            </BlurView>
            </Modal>
            }

To position the modal in the center of the application, you have to use absolute positioning.
Copy/paste the code below into the Styleshset.create object to position the modal center.

blur:{
        flex: 1, 
        alignItems: "center", 
        justifyContent: "center"
    },
    absolute:{
        position: 'absolute',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
    },

Conclusion

Whether you’re looking to build a relatively basic or complex mobile app, styling in React Native is as simple as writing CSS for a web application. You can read more about available react-native props in the React Native docs.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Emmanuel Etukudo I am a full-stack developer with more than five years of experience, with a preference for JavaScript, Node.js, Go, React, Redux, and MongoDB.

One Reply to “React Native styling tutorial with examples”

Leave a Reply