Skip to content
Related Articles

Related Articles

Animated shared layout using framer-motion and React.js

View Discussion
Improve Article
Save Article
  • Last Updated : 12 Mar, 2021

The following approach covers how to create an animated shared layout using framer-motion and ReactJS.


  1. Knowledge of JavaScript (ES6)
  2. Knowledge of HTML/CSS.
  3. Basic knowledge of ReactJS.

Creating React Application And Installing Module:

  • Step 1: Create a React application using the following command:

    npx create-react-app animated-layout
  • Step 2: After creating your project folder i.e. animated-layout, move to it using the following command.

    cd animated-layout
  • Step 3: Add the npm packages you will need during the project :

    npm install framer-motion

Now open the src folder and delete the following files and create a JavaScript file named Item.js.

  • logo.svg
  • serviceWorker.js
  • setupTests.js
  • App.test.js (if any)
  • index.css

Project Structure: Your project structure tree should look like this:

Folder structure


  • We are going to create an Item component that is the animated layout using react useState hook and framer-motion components motion and AnimatePresence.
  • Content component is used to create Item’s (animated shared layout) content using HTML img tag and div & framer-motion component motion.
  • The toggleOpen is a utility function to set the ‘isOpen’ value not (!) of its last value.
  • In App.js, itemList is for the number of animated shared layout we want to create, in our case it is 3.
  • In App.js, we are going to use framer-motion AnimatedSharedLayout component to wrap the imported Item component and map through ‘itemsList’ array to render animated layouts.


import React from "react";
import { AnimateSharedLayout } from "framer-motion";
import Item from "./Item";
import "./styles.css";
// This is an example of animating shared layouts 
// using react and framer-motion library.
const itemsList = [
    index: 0,
    content: `Motion components are DOM primitives 
  optimised for 60fps animation and gestures.`
    index: 1,
    content: `Motion can animate:
    Numbers: 0, 10 etc.
    Strings containing numbers: "0vh", "10px" etc.`
    index: 2,
    content: `Transform properties are accelerated by the GPU,
     and therefore animate smoothly. `
const App = () => {
  return (
    // The framer-motion component to wrap Item component to animate it 
      {/* Mapping through itemList array to render layouts*/}
      { => (
        <Item key={item.index} content={item.content} />
export default App;


import React, { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
const Content = ({ content }) => {
  return (
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      <div className="row">{content}</div>
const Item = ({ content }) => {
  // React useState hook is used to manage the state of 'isOpen'
  // that in turn toggles shared layout, user clicks on
  const [isOpen, setIsOpen] = useState(false);
  // Utility function to set 'isOpen' '!'(not) of its last value
  const toggleOpen = () => setIsOpen(!isOpen);
  return (
      title="Click to reveal"
      initial={{ borderRadius: [25] }}
      <motion.div className="avatar" layout>
        {" "}
        />{" "}
      <br />
      <AnimatePresence>{isOpen && <Content content={content} />}
export default Item;


body {
  min-height: 100vh;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
* {
  box-sizing: border-box;
li {
  list-style: none;
  margin: 0;
  padding: 0;
ul {
  width: 300px;
  display: flex;
  flex-direction: column;
  background: #fcfcfc;
  padding: 20px;
  border-radius: 25px;
li {
  background-color: rgba(214, 214, 214, 0.5);
  border-radius: 10px;
  padding: 20px;
  margin-bottom: 20px;
  overflow: hidden;
  cursor: pointer;
  width: 300px;
li:last-child {
  margin-bottom: 0px;
.avatar {
  width: 40px;
  height: 40px;
  border-radius: 20px;
.avatar img {
  width: 40px;
  border-radius: 100%;
.row {
  margin-top: 12px;
img {
  width: 250px;
  height: 40px;

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:

My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!