Cards full screen expand and shrink back React and Framer Motion

Abhik
3 min readOct 24, 2020

--

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:

Expand Shrink Cards with react and framer motion

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;

HOPE THIS HELPS !!🎉🎉

--

--