Animated expanding card using framer-motion and ReactJS

17 Jan, 2022
In this article, we are going to learn how to create an animated expanding card using react and framer.
Prerequisites:
Knowledge of JavaScript (ES6).JavaScript inbuilt methods we are going to make use are :Arrow function (ES6)Ternary operatorObjects in JavaScriptKnowledge of HTML/CSS.Basic knowledge of ReactJS
Knowledge of JavaScript (ES6).JavaScript inbuilt methods we are going to make use are :Arrow function (ES6)Ternary operatorObjects in JavaScript
JavaScript inbuilt methods we are going to make use are :
Arrow function (ES6)Ternary operatorObjects in JavaScript
Arrow function (ES6)
Ternary operator
Objects in JavaScript
Knowledge of HTML/CSS.
Basic knowledge of ReactJS
React hooks used in building this application are:
React useState
React useState
Framer: components and hooks we are going to make use of in this tutorial are :
https://www.framer.com/api/frame/https://www.framer.com/api/scroll/https://www.framer.com/api/utilities/#useanimation
https://www.framer.com/api/frame/
https://www.framer.com/api/scroll/
https://www.framer.com/api/utilities/#useanimation
Creating React Application And Installing Module :
Step 1: Now, you will start a new project using create-react-app so open your terminal and type.$ npx create-react-app animated-card
Step 1: Now, you will start a new project using create-react-app so open your terminal and type.
$ npx create-react-app animated-card
Step 2: After creating your project folder i.e. animated-card, move to it using the following command.$ cd animated-card
Step 2: After creating your project folder i.e. animated-card, move to it using the following command.
$ cd animated-card
Step 3: Add the npm packages you will need during the project.$ npm install framer react-icons
// For yarn
$ yarn add framer react-icons
Step 3: Add the npm packages you will need during the project.
$ npm install framer react-icons
// For yarn
$ yarn add framer react-icons
Open the src folder and delete the following files :
logo.svgserviceWorker.jssetupTests.jsApp.cssApp.jsApp.test.js (if any)
logo.svg
serviceWorker.js
setupTests.js
App.css
App.js
App.test.js (if any)
Create a file named Card.js.
Project structure: Your project structure tree should look like this :
Project structure
Example: 
index.js
import React from "react";import { Frame, Scroll } from "framer";import Card from "./Card";import ReactDOM from "react-dom";  import "./index.css";  // main App HOCexport const App = () => {  return (    <Frame height={"100%"} width={"100%"} background={"#333"}>      <Frame width={375} height={"100%"} background={"#FFF"} center>        <Scroll width={375} height={"100%"}>          {/* Card component with props yPos,title,subtitle */}          <Card            yPos={48}            title={"GEEKSFORGEEKS"}            subtitle="Don't learn alone"          />          <Card            yPos={48 + 300 + 24}            title={"reactJS"}            subtitle="Most starred JavaScript library"          />        </Scroll>      </Frame>    </Frame>  );};  const rootElement = document.getElementById("root");ReactDOM.render(<App />, rootElement);
index.css
body {  margin: 0;  cursor: pointer;}
Card.js
import React, { useState } from "react";import { ImCross } from "react-icons/im";import { Frame, Scroll, useAnimation } from "framer";  // Card component with destructured props :// yPos, title, subtitleconst Card = ({ yPos, title, subtitle }) => {    // useState hook to manage the state of  // expanding of card  const [state, setState] = useState(false);    // utility function to handle  // onTap on card component  const handleTap = () => {    state ? controls.start({ y: 0 }) : setState(!state);  };    const controls = useAnimation();    // Variants allow you to define animation  // states and organise them by name.  // They allow you to control animations   // throughout a component  // tree by switching a single animate prop.  const variants = {    active: {      width: 320,      height: 800,      borderRadius: 0,      overflow: "visible",      left: 28,      right:0,      y: 0,      transition: { duration: 0.125,                     type: "spring",                     damping: 10,                     mass: 0.6 }    },    inactive: {      width: 280,      height: 280,      borderRadius: 24,      overflow: "hidden",      left: 45,      y: yPos,      transition: { duration: 0.125,                     type: "spring",                     damping: 10,                    mass: 0.6 }    }  };    return (    // basic container for layout, styling,    // animation and events.    <Frame      y={yPos}      variants={variants}      animate={state ? "active" : "inactive"}      width={300}      height={300}      borderRadius={24}      style={state ? { zIndex: 10 } : { zIndex: 1 }}      left={37.5}      onTap={handleTap}      shadow={        state          ? "0 0 0 0 rgba(0, 0, 0, 0)"          : "0px 0px 20px 0px rgba(0, 0, 0, .25)"      }    >      <Scroll        width="100%"        height="100%"        backgroundColor={null}        scrollAnimate={controls}      >        <Frame          position="relative"          backgroundColor={"#09a960"}          width="100%"          height={300}        />        <Frame position="relative"                height={1200}                background="white" />          <Frame          top={20}          left={20}          height={""}          width={""}          background={null}          style={{            color: "white",            fontFamily: "sans-serif"          }}        >          <span style={{ fontSize: "1.6em",                          fontWeight: 600 }}>                        {title}          </span>          <br />          <span            style={{              fontSize: "1em",              fontWeight: 500,              opacity: 0.5            }}          >            {subtitle}          </span>        </Frame>      </Scroll>      {state && (        <Frame          borderRadius={20}          size={15}          top={15}          right={20}          backgroundColor={"#09a960"}          onTap={() => {            setState(false);          }}        >          <ImCross color="red" />        </Frame>      )}    </Frame>  );};  export default Card;
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:
adnanirshad158
CSS-Properties
Framer-motion
ReactJS
Web Technologies
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.