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 :
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: