'How to prevent content jumping in framer-motion animation when transitioning between two pages

I have essentially the following setup:

<AnimatePresence initial={false}>
  {value ? (
    <motion.div>
      {/* Page 1 content */}
    </motion.div>
  ) : (
    <motion.div>
      {/* Page 2 content */}
    </motion.div>
  )}
</AnimatePresence>

When value changes from true to false, I want page 1 to slide out to the left while at the same time page 2 slides in from the right. This is very similar to how slideshows work, or page transitions on iOS apps.

I have a simple example set up on CodeSanbox: https://codesandbox.io/s/laughing-leftpad-4kin7k?file=/src/App.js:272-1064. What happens when I toggle value is that the pages slide to the left as expected, but because the pages are different heights, they cause the content under them to jump down. Also, since both pages are rendered at the same time during the animation, the first page causes the 2nd page to render below it as well, so when the animation completes, page 2 jumps up.

enter image description here

How can I do this sort of animation without the content jumping around? Ideally, I want:

  • Page 2 to appear to the right of page 1, not rendered below it.
    • This will prevent page 2 from jumping up when page 1 unmounts after its slide out animation completes.
  • The height of the container to animate to the height of page 2.
    • This will prevent the content under the pages from jumping down when the animation starts.


Solution 1:[1]

Unfortunately I'm running out of time to dig into finding a technical answer, but I used this Framer-Motion Example as a guide.

Steps:

  1. Wrapped animate presence in a div.
  2. Added Flex and fixed height to max height of largest component in animate presence.
  3. Added duration of 0.5 to exit animations
  4. Added delay of 0.5 to allow exit animations to complete

Before After

Here's the sandbox I used: https://codesandbox.io/s/crazy-forest-5m1p7x?file=/src/App.js

Solution 2:[2]

You need to define exitBeforeEnter property to the AnimatePresence component, which should fix your issue!

Something like this :

<AnimatePresence exitBeforeEnter initial={false}> 
    <motion.div>....</motion.div>
</AnimatePresence>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 corn
Solution 2 Vimal Thanikachalam