Animated sliding page gallery using framer-motion and React.js
Last Updated :
24 Jul, 2024
The following approach covers how to create an animated sliding page gallery using framer-motion and ReactJS.
Prerequisites:
- Knowledge of JavaScript (ES6)
- Knowledge of HTML and CSS.
- Basic knowledge of ReactJS.
Creating React Application And Installing Module:
Step 1: Create a React application using the following command:
$ npx create-react-app page-gallery
Step 2: After creating your project folder i.e. page-gallery, move to it using the following command.
$ cd page-gallery
Step 3: Add the npm packages you will need during the project.
$ npm install framer-motion @popmotion/popcorn
Open the src folder and delete the following files:
- logo.svg
- serviceWorker.js
- setupTests.js
- App.test.js (if any)
- index.css.
Create a file named PageSlider.js.
Project structure: The project structure tree should look like this:
Project structureFilename: App.js
JavaScript
import React from "react";
import { useState } from "react";
import { motion, AnimateSharedLayout } from "framer-motion";
import PageSlider from "./PageSlider";
import "./styles.css";
const Pagination = ({ currentPage, setPage }) => {
// Wrap all the pagination Indicators
// with AnimateSharedPresence
// so we can detect when Indicators
// with a layoutId are removed/added
return (
<AnimateSharedLayout>
<div className="Indicators">
{pages.map((page) => (
<Indicator
key={page}
onClick={() => setPage(page)}
isSelected={page === currentPage}
/>
))}
</div>
</AnimateSharedLayout>
);
};
const Indicator = ({ isSelected, onClick }) => {
return (
<div className="Indicator-container" onClick={onClick}>
<div className="Indicator">
{isSelected && (
// By setting layoutId, when this component
// is removed and a new one is added elsewhere,
// the new component will animate out from the old one.
<motion.div className="Indicator-highlight"
layoutId="highlight" />
)}
</div>
</div>
);
};
const pages = [0, 1, 2, 3, 4];
const App = () => {
/* We keep track of the pagination direction as well as
* current page, this way we can dynamically generate different
* animations depending on the direction of travel */
const [[currentPage, direction], setCurrentPage] = useState([0, 0]);
function setPage(newPage, newDirection) {
if (!newDirection) newDirection = newPage - currentPage;
setCurrentPage([newPage, newDirection]);
}
return (
<>
<PageSlider
currentPage={currentPage}
direction={direction}
setPage={setPage}
/>
<Pagination currentPage={currentPage}
setPage={setPage} />
</>
);
};
export default App;
Filename: PageSlider.js
JavaScript
import React from "react";
import { useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { wrap } from "@popmotion/popcorn";
// Variants in framer-motion define visual states
// that a rendered motion component can be in at
// any given time.
const xOffset = 100;
const variants = {
enter: (direction) => ({
x: direction > 0 ? xOffset : -xOffset,
opacity: 0
}),
active: {
x: 0,
opacity: 1,
transition: { delay: 0.2 }
},
exit: (direction) => ({
x: direction > 0 ? -xOffset : xOffset,
opacity: 0
})
};
const pages = [0, 1, 2, 3, 4];
const PageSlider = ({ currentPage, setPage, direction }) => {
/* Add and remove pages from the array to checkout
how the gestures and pagination animations are
fully data and layout-driven. */
const hasPaginated = useRef(false);
function detectPaginationGesture(e, { offset }) {
if (hasPaginated.current) return;
let newPage = currentPage;
const threshold = xOffset / 2;
if (offset.x < -threshold) {
// If user is dragging left, go forward a page
newPage = currentPage + 1;
} else if (offset.x > threshold) {
// Else if the user is dragging right,
// go backwards a page
newPage = currentPage - 1;
}
if (newPage !== currentPage) {
hasPaginated.current = true;
// Wrap the page index to within the
// permitted page range
newPage = wrap(0, pages.length, newPage);
setPage(newPage, offset.x < 0 ? 1 : -1);
}
}
return (
<div className="slider-container">
<AnimatePresence
// This will be used for components to resolve
// exit variants. It's necessary as removed
// components won't rerender with
// the latest state (as they've been removed)
custom={direction}>
<motion.div
key={currentPage}
className="slide"
data-page={currentPage}
variants={variants}
initial="enter"
animate="active"
exit="exit"
drag="x"
onDrag={detectPaginationGesture}
onDragStart={() => (hasPaginated.current = false)}
onDragEnd={() => (hasPaginated.current = true)}
// Snap the component back to the center
// if it hasn't paginated
dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0 }}
// This will be used for components to resolve all
// other variants, in this case initial and animate.
custom={direction}
/>
</AnimatePresence>
</div>
);
};
export default PageSlider;
Filename: App.css
CSS
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden;
background: #09a960;
}
* {
box-sizing: border-box;
}
.App {
font-family: sans-serif;
text-align: center;
}
.slider-container {
position: relative;
width: 600px;
height: 600px;
}
.slide {
border-radius: 5px;
background: white;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
/* position of indicator container */
.Indicators {
display: flex;
justify-content: center;
margin-top: 30px;
}
.Indicator-container {
padding: 20px;
cursor: pointer;
}
.Indicator {
width: 10px;
height: 10px;
background: #fcfcfc;
border-radius: 50%;
position: relative;
}
.Indicator-highlight {
top: -2px;
left: -2px;
background: #09f;
border-radius: 50%;
width: 14px;
height: 14px;
position: absolute;
}
Step to Run Application: Run the application using the following command from the root directory of the project:
$ npm start
Output: Now open your browser and go to http://localhost:3000/, you will see the following output:
Similar Reads
React Interview Questions and Answers React is an efficient, flexible, and open-source JavaScript library that allows developers to create simple, fast, and scalable web applications. Jordan Walke, a software engineer who was working for Facebook, created React. Developers with a JavaScript background can easily develop web applications
15+ min read
React Tutorial React is a powerful JavaScript library for building fast, scalable front-end applications. Created by Facebook, it's known for its component-based structure, single-page applications (SPAs), and virtual DOM,enabling efficient UI updates and a seamless user experience.Note: The latest stable version
7 min read
90+ React Projects with Source Code [2025] React, managed by Facebook and a vibrant community of developers and companies, is a JavaScript library designed to craft dynamic user interfaces. It empowers developers with concepts like React web apps, components, props, states, and component lifecycles. With a primary focus on building single-pa
12 min read
Frontend Developer Interview Questions and Answers Frontend development is an important part of web applications, and it is used to build dynamic and user-friendly web applications with an interactive user interface (UI). Many companies are hiring skilled Frontend developers with expertise in HTML, CSS, JavaScript, and modern frameworks and librarie
15+ min read
React Introduction ReactJS is a component-based JavaScript library used to build dynamic and interactive user interfaces. It simplifies the creation of single-page applications (SPAs) with a focus on performance and maintainability.It is developed and maintained by Facebook.The latest version of React is React 19.Uses
8 min read
React Hooks ReactJS Hooks are one of the most powerful features of React, introduced in version 16.8. They allow developers to use state and other React features without writing a class component. Hooks simplify the code, make it more readable, and offer a more functional approach to React development. With hoo
10 min read
React JSX JSX stands for JavaScript XML, and it is a special syntax used in React to simplify building user interfaces. JSX allows you to write HTML-like code directly inside JavaScript, enabling you to create UI components more efficiently. Although JSX looks like regular HTML, itâs actually a syntax extensi
6 min read
React Router React Router is a library for handling routing and navigation in React JS Applications. It allows you to create dynamic routes, providing a seamless user experience by mapping various URLs to components. It enables navigation in a single-page application (SPA) without refreshing the entire page.This
6 min read
ReactJS Virtual DOM ReactJS Virtual DOM is an in-memory representation of the actual DOM (Document Object Model). React uses this lightweight JavaScript object to track changes in the application state and efficiently update the actual DOM only where necessary.What is the Virtual DOM?The Virtual DOM (VDOM) is a lightwe
4 min read
React Lifecycle In React, the lifecycle refers to the various stages a component goes through. These stages allow developers to run specific code at key moments, such as when the component is created, updated, or removed. By understanding the React lifecycle, you can better manage resources, side effects, and perfo
7 min read