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 :
- Knowledge of HTML/CSS.
- Basic knowledge of ReactJS
React hooks used in building this application are:
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
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 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
Open the src folder and delete the following files :
- 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 HOC export 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, subtitle const 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: