In our mobile phone , we often see any app when we tap on it, it expands to full screen and when you close it , it shrinks back to its initial position and initial size.
So if you want to recreate those animated transition inside your react website then read this article:
Step 1: Install framer-motion
npm install framer-motion
Step 2 : Creating the Card Component
But first , we import the AnimatedSharedLayout and motion from ‘ framer-motion’
import {AnimateSharedLayout, motion} from 'framer-motion'
Then we write the code for Card Component
function Card({value}) {const [open,setOpen]=useState(false)return <AnimateSharedLayout>{open?{/* DISPLAY EXPANDED CARD */}:{/* DISPLAY NORMAL CARD */}}</AnimateSharedLayout>}export default Card;
Let me explain the above code real quick !
AnimatedSharedLayout lets us transition two different layouts as if they are one layout. For example, if you have a square div and a circle div both showing different contents then with the help of AnimatedSharedLayout transition will feel like the square transforms into a circle or vice-versa.
So what we are doing in this tutorial is :
- when we open this card that is tap on the NORMAL CARD it will transform to EXPANDED CARD ,
- on tapping to EXPANDED CARD it will transform back to NORMAL CARD.
Step 3: Creating the Normal Card
Design the normal card as per your wish it’s more of css trick than react. Here I share my own css and react code:
<motion.div onClick={()=>setOpen(true)} className="normal-card" layoutId="expandable-card" style={{background:value}}><motion.h1 layoutId="expandable-card-h">{value}</motion.h1></motion.div>
Please Note : the layoutId prop is mandatory for AnimatedSharedLayout to work
/* normal card css*/.normal-card{width: 200px;height:200px;display: grid;place-items: end center ;margin: 10px;}.normal-card h1{font-size: 18px;color:var(--fg);padding: 5px;text-align: center;}
Step 4 : Creating the EXPANDED CARD
In this card I am having a h2 and a p tag,you can have anything you want
<motion.div onClick={()=>setOpen(false)} className='expanded-card' layoutId="expandable-card" style={{background:value}}><motion.h2 className='expanded-card-h' layoutId="expandable-card-h"> Expanded {value}</motion.h2><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.Voluptate aliquam molestiae ratione sint magnam sequi fugiat ullam earum distinctio fuga iure, ad odit repudiandae modi est alias ipsum aperiam.Culpa?</p></motion.div>
Make Sure the layoutId is same as that of NORMAL CARD
/* expand card css*/.expanded-card{position: absolute;top:0px;left:0px;width: 100vw;height:100vh;z-index: 1;display: grid;place-items: center;}.expanded-card-h{font-size: 27px;color:var(--fg);width: 300px;padding: 5px;place-self: end center;}.expanded-card p{width:300px;padding: 5px;place-self: start center;}
That’s it ! We are done !
Now you can run npm start to view your animations
Also Note: If you face any jarring animation in chrome or edge , where there are lines left after animations
Then make more motion tags inside the cards and make them have same layoutId
For Example:
{/* IN EXPANDED CARD */}<motion.h2 className='expanded-card-h' layoutId="expandable-card-h">Expanded {value}</motion.h2>{/* IN NORMAL CARD */}<motion.h1 layoutId="expandable-card-h">{value}</motion.h1>
This trick can fix the jarring animations
Final Code
import {AnimateSharedLayout, motion} from 'framer-motion'function Card({value}) {const [open,setOpen]=useState(false)return <AnimateSharedLayout>{open?{/* EXPANDED CARD */}
<motion.div onClick={()=>setOpen(false)} className='expanded-card' layoutId="expandable-card" style={{background:value}}><motion.h2 className='expanded-card-h' layoutId="expandable-card-h"> Expanded {value}</motion.h2><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.Voluptate aliquam molestiae ratione sint magnam sequi fugiat ullam earum distinctio fuga iure, ad odit repudiandae modi est alias ipsum aperiam.Culpa?</p></motion.div>:{/* NORMAL CARD */}
<motion.div onClick={()=>setOpen(true)} className="normal-card" layoutId="expandable-card" style={{background:value}}><motion.h1 layoutId="expandable-card-h">{value}</motion.h1></motion.div>}</AnimateSharedLayout>}export default Card;