Thursday, October 9, 2025
HomeLanguagesAnimated shared layout using framer-motion and React.js

Animated shared layout using framer-motion and React.js

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

Prerequisites:

  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

Example:

  • 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.

App.js




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 
    <AnimateSharedLayout>
      {/* Mapping through itemList array to render layouts*/}
      {itemsList.map((item) => (
        <Item key={item.index} content={item.content} />
      ))}
    </AnimateSharedLayout>
  );
};
  
export default App;


Item.js




import React, { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
  
const Content = ({ content }) => {
  
    "20200817185016/gfg_complete_logo_2x-min.png"
  
  return (
    <motion.div
      layout
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    >
      <img
        src={url}
        alt="neveropen"
      />
      <div className="row">{content}</div>
    </motion.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);
  
    "27UlohMeBLxyUdhs9hUbc-Agw=s900-c-k-c0x00ffffff-no-rj"
  
  return (
    <motion.li
      layout
      title="Click to reveal"
      onClick={toggleOpen}
      initial={{ borderRadius: [25] }}
    >
      <motion.div className="avatar" layout>
        {" "}
        <img
          src={url}
          alt="gfg"
        />{" "}
      </motion.div>
      <br />
      <AnimatePresence>{isOpen && <Content content={content} />}
      </AnimatePresence>
    </motion.li>
  );
};
  
export default Item;


styles.css




body {
  min-height: 100vh;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
  
* {
  box-sizing: border-box;
}
  
ul,
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:

Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, neveropen Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!
RELATED ARTICLES

Most Popular

Dominic
32342 POSTS0 COMMENTS
Milvus
87 POSTS0 COMMENTS
Nango Kala
6713 POSTS0 COMMENTS
Nicole Veronica
11876 POSTS0 COMMENTS
Nokonwaba Nkukhwana
11937 POSTS0 COMMENTS
Shaida Kate Naidoo
6833 POSTS0 COMMENTS
Ted Musemwa
7092 POSTS0 COMMENTS
Thapelo Manthata
6786 POSTS0 COMMENTS
Umr Jansen
6789 POSTS0 COMMENTS