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:
- What is React Native?
- React Native styling example
- How styling in React Native works
- Building and styling a React Native app
- Styling React Native components
- Breaking down the code
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:
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:
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:
Folder structure
The folder structure for our React Native styling example is as follows.
assets
contains all the application’s assets, includingfonts
,images
, andicons
constants
containsicons.js
,images.js
,theme.js
, andindex.js
. All assets are stored inJavaScript
constantsscreens
containsHome.js
andindex.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:
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.
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.
LogRocket: Instantly recreate issues in your React Native apps.

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
React native global content
Thanks for sharing blog. I really appreciate this blog because this helps me a lot.
Some libs like rn-css would help a lot for styling