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:
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); |
body { margin : 0 ;
cursor : pointer ;
} |
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: