If you’ve ever wondered how to best use horizontal spaces on mobile applications, you should consider using carousels. Carousels help users cycle through series of content that can be displayed both horizontally and vertically, making it easy for developers to display content on various types of devices, especially mobile ones.
In this tutorial, we’ll create a carousel in a mobile application using React Native.
Prerequisites
We will be creating a carousel with a Tinder animation, but, before we begin, this tutorial assumes you have the following prerequisites:
- Knowledge of JavaScript (ES6+)
- Familiarity with React v16+
- Knowledge of React Native
- A code editor
- Basic knowledge of a terminal
- npm and/or yarn
- Node.js (v10+)
Getting started
First, we’ll bootstrap our application with Expo. Open your terminal and type the code below to install the Expo CLI if you don’t have it installed already:
npm install expo-cli --global
After installing Expo, we can use it to initialize React Native. Navigate to a directory that you want to add your project to and type the following:
expo init ReactNativeCarouselTutorial
Choose a blank template in the managed workflow section.
After it’s installed all the necessary dependencies, navigate to the project directory in your terminal and start your project:
expo start
This launches Metro Bundler in your browser, giving you the option of running the application on your chosen emulator. You should be presented with a screenshot similar to the one below:
Creating the carousel
To create a carousel, open your terminal, navigate to the project directory, and type this command:
npm install --save react-native-snap-carousel
This installs react-native-snap-carousel, which is a package we’ll use to create the carousel.
After installation, create a data.js
file in your root directory and paste the code below:
export default data = [ { title: "Aenean leo", body: "Ut tincidunt tincidunt erat. Sed cursus turpis vitae tortor. Quisque malesuada placerat nisl. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.", imgUrl: "https://picsum.photos/id/11/200/300" }, { title: "In turpis", body: "Aenean ut eros et nisl sagittis vestibulum. Donec posuere vulputate arcu. Proin faucibus arcu quis ante. Curabitur at lacus ac velit ornare lobortis. ", imgUrl: "https://picsum.photos/id/10/200/300" }, { title: "Lorem Ipsum", body: "Phasellus ullamcorper ipsum rutrum nunc. Nullam quis ante. Etiam ultricies nisi vel augue. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc.", imgUrl: "https://picsum.photos/id/12/200/300" } ]
The data file is an array that contains mock data that we will use to populate our carousel.
Next, create a file called CarouselCardItem.js
and open it. Insert the following code:
import React from 'react' import { View, Text, StyleSheet, Dimensions, Image } from "react-native" export const SLIDER_WIDTH = Dimensions.get('window').width + 80 export const ITEM_WIDTH = Math.round(SLIDER_WIDTH * 0.7) const CarouselCardItem = ({ item, index }) => { return ( <View style={styles.container} key={index}> <Image source={{ uri: item.imgUrl }} style={styles.image} /> <Text style={styles.header}>{item.title}</Text> <Text style={styles.body}>{item.body}</Text> </View> ) } const styles = StyleSheet.create({ container: { backgroundColor: 'white', borderRadius: 8, width: ITEM_WIDTH, paddingBottom: 40, shadowColor: "#000", shadowOffset: { width: 0, height: 3, }, shadowOpacity: 0.29, shadowRadius: 4.65, elevation: 7, }, image: { width: ITEM_WIDTH, height: 300, }, header: { color: "#222", fontSize: 28, fontWeight: "bold", paddingLeft: 20, paddingTop: 20 }, body: { color: "#222", fontSize: 18, paddingLeft: 20, paddingLeft: 20, paddingRight: 20 } }) export default CarouselCardItem
The CarouselCardItem
implements the look of the cards in the carousel. It returns a component that will display the item passed as props.
Now, let’s create a component that will be responsible for displaying the carousel. Create a file called CarouselCards
, open it, and enter the following code:
import React from 'react' import { View } from "react-native" import Carousel from 'react-native-snap-carousel' import CarouselCardItem, { SLIDER_WIDTH, ITEM_WIDTH } from './CarouselCardItem' import data from './data' const CarouselCards = () => { const isCarousel = React.useRef(null) return ( <View> <Carousel layout="tinder" layoutCardOffset={9} ref={isCarousel} data={data} renderItem={CarouselCardItem} sliderWidth={SLIDER_WIDTH} itemWidth={ITEM_WIDTH} inactiveSlideShift={0} useScrollView={true} /> </View> ) } export default CarouselCards
We use the Carousel
component from the react-native-snap-carousel package to implement the carousel. The props accepted by the component include:
layout
: it defines the way the items are rendered. The options include default, stack, and TinderlayoutCardOffset
: it is used to increase or decrease the default card offset in both the stack and Tinder layoutsref
: creates a reference to an instance of the carouseldata
: array of items to loop onrenderItem
: takes an item from the data and renders it into the listsliderWidth
: width in pixel of the carouselitemWidth
: width in pixel of the carousel itemuseScrollView
: choose to use a ScrollView component as opposed to a Flatlist component for performance reasonsonSnapToItem
: snaps to a carousel item programmatically
Adding pagination
We can add pagination so users can skip to a certain item in the carousel without having to swipe continuously. The first thing we have to do is import the component. To do this, go to the line where we imported the carousel component:
import Carousel from 'react-native-snap-carousel'
And refactor it to look like this:
import Carousel, { Pagination } from 'react-native-snap-carousel'
Next, create a state to store the current pagination index:
const [index, setIndex] = React.useState(0)
After that, paste the following code below the carousel component:
<Pagination dotsLength={data.length} activeDotIndex={index} carouselRef={isCarousel} dotStyle={{ width: 10, height: 10, borderRadius: 5, marginHorizontal: 0, backgroundColor: 'rgba(0, 0, 0, 0.92)' }} inactiveDotOpacity={0.4} inactiveDotScale={0.6} tappableDots={true} />
This renders the pagination component, which, by default, is a list of dots. The pagination component accepts the following props:
dotsLength
: the number of dots to displayactiveDotIndex
: index of the current active dotcarouselRef
: a reference to the carousel component, which the pagination is linked todotStyle
: dots style to be merged with the defaultinactiveDotOpacity
: the value of opacity applied to inactive dotsinactiveDotScale
: value of thescale
transform applied to inactive dotstappableDots
: makes default dots tappable, so that when a dot is tapped, the carousel will slide to the corresponding item
The modified CarouselCards
component should resemble the code below:
import React from 'react' import { View } from "react-native" import Carousel, { Pagination } from 'react-native-snap-carousel' import CarouselCardItem, { SLIDER_WIDTH, ITEM_WIDTH } from './CarouselCardItem' import data from './data' const CarouselCards = () => { const [index, setIndex] = React.useState(0) const isCarousel = React.useRef(null) return ( <View> <Carousel layout="tinder" layoutCardOffset={9} ref={isCarousel} data={data} renderItem={CarouselCardItem} sliderWidth={SLIDER_WIDTH} itemWidth={ITEM_WIDTH} onSnapToItem={(index) => setIndex(index)} useScrollView={true} /> <Pagination dotsLength={data.length} activeDotIndex={index} carouselRef={isCarousel} dotStyle={{ width: 10, height: 10, borderRadius: 5, marginHorizontal: 0, backgroundColor: 'rgba(0, 0, 0, 0.92)' }} inactiveDotOpacity={0.4} inactiveDotScale={0.6} tappableDots={true} /> </View> ) } export default CarouselCards
Now, go to your App.js
file and refactor the code there to look like this:
import React from 'react' import { SafeAreaView, StyleSheet } from 'react-native' import CarouselCards from './CarouselCards' export default function App() { return ( <SafeAreaView style={styles.container}> <CarouselCards /> </SafeAreaView> ); } const styles = StyleSheet.create({ container: { backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', padding: 50 }, });
After saving, you should be presented with a screenshot similar to this:
Congratulations! You’ve finished your carousel.
Conclusion
In this tutorial, we walked through implementing a carousel with React Native. We used react-native-snap-carousel, which provides many options for creating carousels. If you’d like to see a Snack showcase of this tutorial, check it out here.
LogRocket: 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.
Try it for free.